From 6069ca239e79b57c6e9841c30d9ff3feea48775b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 11 Nov 2016 16:54:46 +0100 Subject: [PATCH] removed 46 stuff --- ImageSharp.46.sln | 34 - src/ImageSharp46/Bootstrapper.cs | 69 - src/ImageSharp46/Colors/Color.cs | 408 --- src/ImageSharp46/Colors/ColorConstants.cs | 179 -- src/ImageSharp46/Colors/ColorDefinitions.cs | 728 ------ src/ImageSharp46/Colors/ColorTransforms.cs | 74 - .../Colors/ColorspaceTransforms.cs | 292 --- src/ImageSharp46/Colors/Colorspaces/Bgra32.cs | 167 -- src/ImageSharp46/Colors/Colorspaces/CieLab.cs | 192 -- src/ImageSharp46/Colors/Colorspaces/CieXyz.cs | 184 -- src/ImageSharp46/Colors/Colorspaces/Cmyk.cs | 195 -- src/ImageSharp46/Colors/Colorspaces/Hsl.cs | 213 -- src/ImageSharp46/Colors/Colorspaces/Hsv.cs | 206 -- .../Colors/Colorspaces/IAlmostEquatable.cs | 30 - src/ImageSharp46/Colors/Colorspaces/YCbCr.cs | 157 -- src/ImageSharp46/Colors/ComponentOrder.cs | 33 - .../Colors/PackedPixel/IPackedBytes.cs | 31 - .../Colors/PackedPixel/IPackedPixel.cs | 16 - .../Colors/PackedPixel/IPackedVector.cs | 42 - src/ImageSharp46/Colors/RgbaComponent.cs | 33 - .../Common/Exceptions/ImageFormatException.cs | 45 - .../Exceptions/ImageProcessingException.cs | 44 - .../Common/Extensions/ByteExtensions.cs | 91 - .../Common/Extensions/ComparableExtensions.cs | 173 -- .../Common/Extensions/EnumerableExtensions.cs | 88 - .../Common/Extensions/StreamExtensions.cs | 30 - .../Common/Extensions/Vector4Extensions.cs | 83 - src/ImageSharp46/Common/Helpers/Guard.cs | 205 -- src/ImageSharp46/Common/Helpers/ImageMaths.cs | 293 --- src/ImageSharp46/Filters/Alpha.cs | 48 - src/ImageSharp46/Filters/BackgroundColor.cs | 30 - src/ImageSharp46/Filters/BinaryThreshold.cs | 48 - src/ImageSharp46/Filters/BlackWhite.cs | 46 - src/ImageSharp46/Filters/Blend.cs | 50 - src/ImageSharp46/Filters/Brightness.cs | 48 - src/ImageSharp46/Filters/ColorBlindness.cs | 85 - src/ImageSharp46/Filters/Contrast.cs | 48 - src/ImageSharp46/Filters/Glow.cs | 102 - src/ImageSharp46/Filters/Grayscale.cs | 52 - src/ImageSharp46/Filters/Hue.cs | 48 - src/ImageSharp46/Filters/Invert.cs | 46 - src/ImageSharp46/Filters/Kodachrome.cs | 46 - src/ImageSharp46/Filters/Lomograph.cs | 46 - .../Filters/Options/ColorBlindness.cs | 53 - .../Filters/Options/EdgeDetection.cs | 63 - .../Filters/Options/GrayscaleMode.cs | 23 - src/ImageSharp46/Filters/Polaroid.cs | 46 - .../Filters/Processors/AlphaProcessor.cs | 85 - .../Processors/BackgroundColorProcessor.cs | 98 - .../Binarization/BinaryThresholdProcessor.cs | 111 - .../Filters/Processors/BlendProcessor.cs | 106 - .../Filters/Processors/BrightnessProcessor.cs | 90 - .../ColorMatrix/BlackWhiteProcessor.cs | 36 - .../ColorBlindness/AchromatomalyProcessor.cs | 36 - .../ColorBlindness/AchromatopsiaProcessor.cs | 36 - .../ColorBlindness/DeuteranomalyProcessor.cs | 33 - .../ColorBlindness/DeuteranopiaProcessor.cs | 33 - .../ColorBlindness/ProtanomalyProcessor.cs | 33 - .../ColorBlindness/ProtanopiaProcessor.cs | 33 - .../ColorMatrix/ColorBlindness/README.md | 4 - .../ColorBlindness/TritanomalyProcessor.cs | 33 - .../ColorBlindness/TritanopiaProcessor.cs | 33 - .../ColorMatrix/ColorMatrixFilter.cs | 96 - .../ColorMatrix/GrayscaleBt601Processor.cs | 34 - .../ColorMatrix/GrayscaleBt709Processor.cs | 32 - .../Processors/ColorMatrix/HueProcessor.cs | 79 - .../ColorMatrix/IColorMatrixFilter.cs | 25 - .../ColorMatrix/KodachromeProcessor.cs | 30 - .../ColorMatrix/LomographProcessor.cs | 38 - .../ColorMatrix/PolaroidProcessor.cs | 48 - .../ColorMatrix/SaturationProcessor.cs | 62 - .../Processors/ColorMatrix/SepiaProcessor.cs | 37 - .../Filters/Processors/ContrastProcessor.cs | 90 - .../Filters/Processors/GlowProcessor.cs | 94 - .../Filters/Processors/IImageFilter.cs | 36 - .../Filters/Processors/ImageFilter.cs | 70 - .../Filters/Processors/InvertProcessor.cs | 68 - .../Filters/Processors/VignetteProcessor.cs | 96 - src/ImageSharp46/Filters/Saturation.cs | 48 - src/ImageSharp46/Filters/Sepia.cs | 46 - src/ImageSharp46/Filters/Vignette.cs | 104 - .../Formats/Bmp/BmpBitsPerPixel.cs | 23 - .../Formats/Bmp/BmpCompression.cs | 63 - src/ImageSharp46/Formats/Bmp/BmpDecoder.cs | 83 - .../Formats/Bmp/BmpDecoderCore.cs | 404 --- src/ImageSharp46/Formats/Bmp/BmpEncoder.cs | 54 - .../Formats/Bmp/BmpEncoderCore.cs | 189 -- src/ImageSharp46/Formats/Bmp/BmpFileHeader.cs | 49 - src/ImageSharp46/Formats/Bmp/BmpFormat.cs | 19 - src/ImageSharp46/Formats/Bmp/BmpInfoHeader.cs | 82 - src/ImageSharp46/Formats/Bmp/README.md | 8 - .../Formats/Gif/DisposalMethod.cs | 37 - src/ImageSharp46/Formats/Gif/GifConstants.cs | 83 - src/ImageSharp46/Formats/Gif/GifDecoder.cs | 65 - .../Formats/Gif/GifDecoderCore.cs | 425 --- src/ImageSharp46/Formats/Gif/GifEncoder.cs | 64 - .../Formats/Gif/GifEncoderCore.cs | 349 --- src/ImageSharp46/Formats/Gif/GifFormat.cs | 19 - src/ImageSharp46/Formats/Gif/LzwDecoder.cs | 228 -- src/ImageSharp46/Formats/Gif/LzwEncoder.cs | 419 --- src/ImageSharp46/Formats/Gif/PackedField.cs | 199 -- src/ImageSharp46/Formats/Gif/README.md | 4 - .../Sections/GifGraphicsControlExtension.cs | 42 - .../Gif/Sections/GifImageDescriptor.cs | 59 - .../Sections/GifLogicalScreenDescriptor.cs | 55 - src/ImageSharp46/Formats/IImageDecoder.cs | 52 - src/ImageSharp46/Formats/IImageEncoder.cs | 51 - src/ImageSharp46/Formats/IImageFormat.cs | 23 - .../Formats/Jpg/Components/Bits.cs | 31 - .../Formats/Jpg/Components/Block.cs | 111 - .../Formats/Jpg/Components/Bytes.cs | 43 - .../Formats/Jpg/Components/Component.cs | 33 - .../Formats/Jpg/Components/FDCT.cs | 160 -- .../Formats/Jpg/Components/FloatIDCT.cs | 208 -- .../Formats/Jpg/Components/GrayImage.cs | 101 - .../Formats/Jpg/Components/Huffman.cs | 89 - .../Formats/Jpg/Components/IDCT.cs | 172 -- .../Formats/Jpg/Components/MagicDCT.cs | 572 ----- .../Formats/Jpg/Components/YCbCrImage.cs | 228 -- src/ImageSharp46/Formats/Jpg/JpegConstants.cs | 230 -- src/ImageSharp46/Formats/Jpg/JpegDecoder.cs | 141 - .../Formats/Jpg/JpegDecoderCore.cs | 2282 ----------------- src/ImageSharp46/Formats/Jpg/JpegEncoder.cs | 100 - .../Formats/Jpg/JpegEncoderCore.cs | 1006 -------- src/ImageSharp46/Formats/Jpg/JpegFormat.cs | 19 - src/ImageSharp46/Formats/Jpg/JpegSubsample.cs | 25 - src/ImageSharp46/Formats/Jpg/README.md | 3 - .../Formats/Png/Filters/AverageFilter.cs | 79 - .../Formats/Png/Filters/FilterType.cs | 45 - .../Formats/Png/Filters/NoneFilter.cs | 44 - .../Formats/Png/Filters/PaethFilter.cs | 98 - .../Formats/Png/Filters/SubFilter.cs | 59 - .../Formats/Png/Filters/UpFilter.cs | 59 - src/ImageSharp46/Formats/Png/PngChunk.cs | 39 - src/ImageSharp46/Formats/Png/PngChunkTypes.cs | 62 - src/ImageSharp46/Formats/Png/PngColorType.cs | 38 - src/ImageSharp46/Formats/Png/PngDecoder.cs | 91 - .../Formats/Png/PngDecoderCore.cs | 645 ----- src/ImageSharp46/Formats/Png/PngEncoder.cs | 93 - .../Formats/Png/PngEncoderCore.cs | 712 ----- src/ImageSharp46/Formats/Png/PngFormat.cs | 19 - src/ImageSharp46/Formats/Png/PngHeader.cs | 62 - src/ImageSharp46/Formats/Png/README.md | 6 - src/ImageSharp46/Formats/Png/Zlib/Adler32.cs | 174 -- src/ImageSharp46/Formats/Png/Zlib/Crc32.cs | 180 -- .../Formats/Png/Zlib/IChecksum.cs | 60 - src/ImageSharp46/Formats/Png/Zlib/README.md | 2 - .../Formats/Png/Zlib/ZlibDeflateStream.cs | 210 -- .../Formats/Png/Zlib/ZlibInflateStream.cs | 214 -- src/ImageSharp46/IO/BigEndianBitConverter.cs | 48 - src/ImageSharp46/IO/EndianBinaryReader.cs | 615 ----- src/ImageSharp46/IO/EndianBinaryWriter.cs | 385 --- src/ImageSharp46/IO/EndianBitConverter.cs | 724 ------ src/ImageSharp46/IO/Endianness.cs | 23 - .../IO/LittleEndianBitConverter.cs | 47 - src/ImageSharp46/Image.cs | 66 - src/ImageSharp46/Image/IImageBase.cs | 119 - src/ImageSharp46/Image/IImageFrame.cs | 18 - src/ImageSharp46/Image/IImageProcessor.cs | 26 - src/ImageSharp46/Image/Image.cs | 361 --- src/ImageSharp46/Image/ImageBase.cs | 166 -- src/ImageSharp46/Image/ImageFrame.cs | 41 - src/ImageSharp46/Image/ImageIOExtensions.cs | 86 - .../Image/ImageProcessingExtensions.cs | 203 -- src/ImageSharp46/Image/ImageProperty.cs | 153 -- src/ImageSharp46/Image/PixelAccessor.cs | 398 --- src/ImageSharp46/Image/PixelRow.cs | 179 -- src/ImageSharp46/ImageProcessor.cs | 25 - src/ImageSharp46/ImageSharp46.csproj | 403 --- src/ImageSharp46/Numerics/Ellipse.cs | 174 -- src/ImageSharp46/Numerics/LongRational.cs | 355 --- src/ImageSharp46/Numerics/Point.cs | 282 -- src/ImageSharp46/Numerics/Rational.cs | 189 -- src/ImageSharp46/Numerics/Rectangle.cs | 291 --- src/ImageSharp46/Numerics/SignedRational.cs | 189 -- src/ImageSharp46/Numerics/Size.cs | 166 -- src/ImageSharp46/PixelAccessor.cs | 90 - .../Profiles/Exif/ExifDataType.cs | 78 - src/ImageSharp46/Profiles/Exif/ExifParts.cs | 41 - src/ImageSharp46/Profiles/Exif/ExifProfile.cs | 239 -- src/ImageSharp46/Profiles/Exif/ExifReader.cs | 515 ---- src/ImageSharp46/Profiles/Exif/ExifTag.cs | 1547 ----------- .../Exif/ExifTagDescriptionAttribute.cs | 52 - src/ImageSharp46/Profiles/Exif/ExifValue.cs | 716 ------ src/ImageSharp46/Profiles/Exif/ExifWriter.cs | 585 ----- src/ImageSharp46/Profiles/Exif/README.md | 3 - src/ImageSharp46/ProgressEventArgs.cs | 23 - src/ImageSharp46/Properties/AssemblyInfo.cs | 39 - src/ImageSharp46/Quantizers/IQuantizer.cs | 34 - .../Quantizers/Octree/OctreeQuantizer.cs | 518 ---- .../Quantizers/Octree/Quantizer.cs | 143 -- .../Quantizers/Options/Quantization.cs | 28 - .../Quantizers/Palette/PaletteQuantizer.cs | 130 - src/ImageSharp46/Quantizers/Quantize.cs | 65 - src/ImageSharp46/Quantizers/QuantizedImage.cs | 94 - src/ImageSharp46/Quantizers/Wu/Box.cs | 58 - src/ImageSharp46/Quantizers/Wu/WuQuantizer.cs | 777 ------ src/ImageSharp46/Samplers/AutoOrient.cs | 87 - src/ImageSharp46/Samplers/BoxBlur.cs | 48 - src/ImageSharp46/Samplers/Crop.cs | 65 - src/ImageSharp46/Samplers/DetectEdges.cs | 161 -- src/ImageSharp46/Samplers/EntropyCrop.cs | 31 - src/ImageSharp46/Samplers/Flip.cs | 31 - src/ImageSharp46/Samplers/GuassianBlur.cs | 48 - src/ImageSharp46/Samplers/GuassianSharpen.cs | 48 - src/ImageSharp46/Samplers/OilPainting.cs | 59 - .../Samplers/Options/AnchorPosition.cs | 58 - src/ImageSharp46/Samplers/Options/FlipType.cs | 28 - .../Samplers/Options/Orientation.cs | 20 - .../Samplers/Options/ResizeHelper.cs | 441 ---- .../Samplers/Options/ResizeMode.cs | 49 - .../Samplers/Options/ResizeOptions.cs | 47 - .../Samplers/Options/RotateType.cs | 33 - src/ImageSharp46/Samplers/Pad.cs | 36 - src/ImageSharp46/Samplers/Pixelate.cs | 55 - .../Processors/CompandingResizeProcessor.cs | 159 -- .../Convolution/BoxBlurProcessor.cs | 101 - .../Convolution/Convolution2DFilter.cs | 129 - .../Convolution/Convolution2PassFilter.cs | 118 - .../Convolution/ConvolutionFilter.cs | 105 - .../EdgeDetection/EdgeDetector2DFilter.cs | 47 - .../EdgeDetectorCompassFilter.cs | 139 - .../EdgeDetection/EdgeDetectorFilter.cs | 40 - .../EdgeDetection/IEdgeDetectorFilter.cs | 29 - .../EdgeDetection/KayyaliProcessor.cs | 47 - .../EdgeDetection/KirschProcessor.cs | 124 - .../EdgeDetection/Laplacian3X3Processor.cs | 34 - .../EdgeDetection/Laplacian5X5Processor.cs | 36 - .../LaplacianOfGaussianProcessor.cs | 36 - .../EdgeDetection/PrewittProcessor.cs | 47 - .../EdgeDetection/RobertsCrossProcessor.cs | 45 - .../EdgeDetection/RobinsonProcessor.cs | 124 - .../EdgeDetection/ScharrProcessor.cs | 47 - .../EdgeDetection/SobelProcessor.cs | 47 - .../Convolution/GuassianBlurProcessor.cs | 142 - .../Convolution/GuassianSharpenProcessor.cs | 180 -- .../Samplers/Processors/CropProcessor.cs | 44 - .../Processors/EntropyCropProcessor.cs | 107 - .../Samplers/Processors/FlipProcessor.cs | 115 - .../Samplers/Processors/IImageSampler.cs | 58 - .../Samplers/Processors/ImageSampler.cs | 119 - .../Samplers/Processors/Matrix3x2Processor.cs | 51 - .../Processors/OilPaintingProcessor.cs | 151 -- .../Samplers/Processors/PixelateProcessor.cs | 111 - .../Processors/ResamplingWeightedProcessor.cs | 171 -- .../Samplers/Processors/ResizeProcessor.cs | 158 -- .../Samplers/Processors/RotateProcessor.cs | 215 -- .../Samplers/Processors/SkewProcessor.cs | 79 - .../Samplers/Resamplers/BicubicResampler.cs | 43 - .../Samplers/Resamplers/BoxResampler.cs | 28 - .../Resamplers/CatmullRomResampler.cs | 28 - .../Samplers/Resamplers/HermiteResampler.cs | 27 - .../Samplers/Resamplers/IResampler.cs | 27 - .../Samplers/Resamplers/Lanczos2Resampler.cs | 34 - .../Samplers/Resamplers/Lanczos3Resampler.cs | 34 - .../Samplers/Resamplers/Lanczos5Resampler.cs | 34 - .../Samplers/Resamplers/Lanczos8Resampler.cs | 34 - .../Resamplers/MitchellNetravaliResampler.cs | 26 - .../Resamplers/NearestNeighborResampler.cs | 23 - .../Samplers/Resamplers/RobidouxResampler.cs | 26 - .../Resamplers/RobidouxSharpResampler.cs | 26 - .../Samplers/Resamplers/SplineResampler.cs | 26 - .../Samplers/Resamplers/TriangleResampler.cs | 34 - .../Samplers/Resamplers/WelchResampler.cs | 33 - src/ImageSharp46/Samplers/Resize.cs | 168 -- src/ImageSharp46/Samplers/Rotate.cs | 62 - src/ImageSharp46/Samplers/RotateFlip.cs | 29 - src/ImageSharp46/Samplers/Skew.cs | 49 - src/ImageSharp46/app.config | 19 - src/ImageSharp46/packages.config | 51 - .../Benchmark/DecodeJpegBenchmark.cs | 69 - .../Colors/ColorConversionTests.cs | 511 ---- tests/ImageSharp.Tests46/Colors/ColorTests.cs | 135 - tests/ImageSharp.Tests46/DctSandbox.cs | 97 - tests/ImageSharp.Tests46/FileTestBase.cs | 51 - .../Formats/Bmp/BitmapTests.cs | 43 - .../Formats/GeneralFormatTests.cs | 158 -- .../Formats/Jpg/JpegTests.cs | 85 - .../Formats/Png/PngTests.cs | 37 - .../ImageSharp.Tests46/Helpers/GuardTests.cs | 242 -- .../Image/ImagePropertyTests.cs | 78 - .../Image/PixelAccessorTests.cs | 168 -- .../ImageSharp.Tests46.csproj | 175 -- .../ImageSharp.Tests46/Numerics/PointTests.cs | 50 - .../Numerics/RationalTests.cs | 115 - .../Numerics/RectangleTests.cs | 66 - .../Numerics/SignedRationalTests.cs | 122 - .../ImageSharp.Tests46/Numerics/SizeTests.cs | 50 - .../Processors/Filters/AlphaTest.cs | 59 - .../Processors/Filters/BackgroundColorTest.cs | 31 - .../Processors/Filters/BinaryThreshold.cs | 40 - .../Processors/Filters/BlackWhiteTest.cs | 31 - .../Processors/Filters/BlendTest.cs | 37 - .../Processors/Filters/BoxBlurTest.cs | 41 - .../Processors/Filters/BrightnessTest.cs | 40 - .../Processors/Filters/ColorBlindnessTest.cs | 46 - .../Processors/Filters/ContrastTest.cs | 39 - .../Processors/Filters/GlowTest.cs | 85 - .../Processors/Filters/GrayscaleTest.cs | 41 - .../Processors/Filters/HueTest.cs | 40 - .../Processors/Filters/InvertTest.cs | 48 - .../Processors/Filters/KodachromeTest.cs | 31 - .../Processors/Filters/LomographTest.cs | 49 - .../Processors/Filters/PolaroidTest.cs | 31 - .../Processors/Filters/SaturationTest.cs | 40 - .../Processors/Filters/SepiaTest.cs | 31 - .../Processors/Filters/VignetteTest.cs | 85 - .../Processors/Samplers/AutoOrientTests.cs | 56 - .../Processors/Samplers/CropTest.cs | 31 - .../Processors/Samplers/DetectEdgesTest.cs | 67 - .../Processors/Samplers/EntropyCropTest.cs | 40 - .../Processors/Samplers/FlipTests.cs | 41 - .../Processors/Samplers/GuassianBlurTest.cs | 40 - .../Samplers/GuassianSharpenTest.cs | 40 - .../Processors/Samplers/OilPaintTest.cs | 60 - .../Processors/Samplers/PadTest.cs | 31 - .../Processors/Samplers/PixelateTest.cs | 59 - .../Processors/Samplers/ResizeTests.cs | 304 --- .../Processors/Samplers/RotateFlipTest.cs | 43 - .../Processors/Samplers/RotateTest.cs | 68 - .../Processors/Samplers/SkewTest.cs | 42 - .../Profiles/Exif/ExifProfileTests.cs | 325 --- .../Exif/ExifTagDescriptionAttributeTests.cs | 38 - .../Profiles/Exif/ExifValueTests.cs | 50 - .../Properties/AssemblyInfo.cs | 23 - tests/ImageSharp.Tests46/TestFile.cs | 56 - tests/ImageSharp.Tests46/TestImages.cs | 65 - .../TestImages/Formats/Bmp/Car.bmp | 3 - .../TestImages/Formats/Bmp/F.bmp | 3 - .../TestImages/Formats/Bmp/neg_height.bmp | 3 - .../TestImages/Formats/Gif/giphy.gif | 3 - .../TestImages/Formats/Gif/rings.gif | 3 - .../TestImages/Formats/Jpg/Calliphora.jpg | 3 - .../TestImages/Formats/Jpg/Floorplan.jpeg | 3 - .../TestImages/Formats/Jpg/cmyk.jpg | 3 - .../TestImages/Formats/Jpg/exif.jpg | 3 - .../TestImages/Formats/Jpg/fb.jpg | 3 - .../Formats/Jpg/gamma_dalai_lama_gray.jpg | 3 - .../TestImages/Formats/Jpg/geneserath.jpg | 3 - .../TestImages/Formats/Jpg/progress.jpg | 3 - .../TestImages/Formats/Jpg/turtle.jpg | 3 - .../TestImages/Formats/Png/blur.png | 3 - .../TestImages/Formats/Png/indexed.png | 3 - .../TestImages/Formats/Png/pd.png | 3 - .../TestImages/Formats/Png/pl.png | 3 - .../TestImages/Formats/Png/splash.png | 3 - tests/ImageSharp.Tests46/app.config | 19 - tests/ImageSharp.Tests46/packages.config | 11 - 348 files changed, 40420 deletions(-) delete mode 100644 ImageSharp.46.sln delete mode 100644 src/ImageSharp46/Bootstrapper.cs delete mode 100644 src/ImageSharp46/Colors/Color.cs delete mode 100644 src/ImageSharp46/Colors/ColorConstants.cs delete mode 100644 src/ImageSharp46/Colors/ColorDefinitions.cs delete mode 100644 src/ImageSharp46/Colors/ColorTransforms.cs delete mode 100644 src/ImageSharp46/Colors/ColorspaceTransforms.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/Bgra32.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/CieLab.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/CieXyz.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/Cmyk.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/Hsl.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/Hsv.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/IAlmostEquatable.cs delete mode 100644 src/ImageSharp46/Colors/Colorspaces/YCbCr.cs delete mode 100644 src/ImageSharp46/Colors/ComponentOrder.cs delete mode 100644 src/ImageSharp46/Colors/PackedPixel/IPackedBytes.cs delete mode 100644 src/ImageSharp46/Colors/PackedPixel/IPackedPixel.cs delete mode 100644 src/ImageSharp46/Colors/PackedPixel/IPackedVector.cs delete mode 100644 src/ImageSharp46/Colors/RgbaComponent.cs delete mode 100644 src/ImageSharp46/Common/Exceptions/ImageFormatException.cs delete mode 100644 src/ImageSharp46/Common/Exceptions/ImageProcessingException.cs delete mode 100644 src/ImageSharp46/Common/Extensions/ByteExtensions.cs delete mode 100644 src/ImageSharp46/Common/Extensions/ComparableExtensions.cs delete mode 100644 src/ImageSharp46/Common/Extensions/EnumerableExtensions.cs delete mode 100644 src/ImageSharp46/Common/Extensions/StreamExtensions.cs delete mode 100644 src/ImageSharp46/Common/Extensions/Vector4Extensions.cs delete mode 100644 src/ImageSharp46/Common/Helpers/Guard.cs delete mode 100644 src/ImageSharp46/Common/Helpers/ImageMaths.cs delete mode 100644 src/ImageSharp46/Filters/Alpha.cs delete mode 100644 src/ImageSharp46/Filters/BackgroundColor.cs delete mode 100644 src/ImageSharp46/Filters/BinaryThreshold.cs delete mode 100644 src/ImageSharp46/Filters/BlackWhite.cs delete mode 100644 src/ImageSharp46/Filters/Blend.cs delete mode 100644 src/ImageSharp46/Filters/Brightness.cs delete mode 100644 src/ImageSharp46/Filters/ColorBlindness.cs delete mode 100644 src/ImageSharp46/Filters/Contrast.cs delete mode 100644 src/ImageSharp46/Filters/Glow.cs delete mode 100644 src/ImageSharp46/Filters/Grayscale.cs delete mode 100644 src/ImageSharp46/Filters/Hue.cs delete mode 100644 src/ImageSharp46/Filters/Invert.cs delete mode 100644 src/ImageSharp46/Filters/Kodachrome.cs delete mode 100644 src/ImageSharp46/Filters/Lomograph.cs delete mode 100644 src/ImageSharp46/Filters/Options/ColorBlindness.cs delete mode 100644 src/ImageSharp46/Filters/Options/EdgeDetection.cs delete mode 100644 src/ImageSharp46/Filters/Options/GrayscaleMode.cs delete mode 100644 src/ImageSharp46/Filters/Polaroid.cs delete mode 100644 src/ImageSharp46/Filters/Processors/AlphaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/BackgroundColorProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/Binarization/BinaryThresholdProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/BlendProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/BrightnessProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/README.md delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt601Processor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt709Processor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/HueProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/KodachromeProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/LomographProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/PolaroidProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/SaturationProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ColorMatrix/SepiaProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ContrastProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/GlowProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/IImageFilter.cs delete mode 100644 src/ImageSharp46/Filters/Processors/ImageFilter.cs delete mode 100644 src/ImageSharp46/Filters/Processors/InvertProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Processors/VignetteProcessor.cs delete mode 100644 src/ImageSharp46/Filters/Saturation.cs delete mode 100644 src/ImageSharp46/Filters/Sepia.cs delete mode 100644 src/ImageSharp46/Filters/Vignette.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpBitsPerPixel.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpCompression.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpDecoder.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpDecoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpEncoder.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpEncoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpFileHeader.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpFormat.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/BmpInfoHeader.cs delete mode 100644 src/ImageSharp46/Formats/Bmp/README.md delete mode 100644 src/ImageSharp46/Formats/Gif/DisposalMethod.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifConstants.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifDecoder.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifDecoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifEncoder.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifEncoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Gif/GifFormat.cs delete mode 100644 src/ImageSharp46/Formats/Gif/LzwDecoder.cs delete mode 100644 src/ImageSharp46/Formats/Gif/LzwEncoder.cs delete mode 100644 src/ImageSharp46/Formats/Gif/PackedField.cs delete mode 100644 src/ImageSharp46/Formats/Gif/README.md delete mode 100644 src/ImageSharp46/Formats/Gif/Sections/GifGraphicsControlExtension.cs delete mode 100644 src/ImageSharp46/Formats/Gif/Sections/GifImageDescriptor.cs delete mode 100644 src/ImageSharp46/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs delete mode 100644 src/ImageSharp46/Formats/IImageDecoder.cs delete mode 100644 src/ImageSharp46/Formats/IImageEncoder.cs delete mode 100644 src/ImageSharp46/Formats/IImageFormat.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/Bits.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/Block.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/Bytes.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/Component.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/FDCT.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/FloatIDCT.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/GrayImage.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/Huffman.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/IDCT.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/MagicDCT.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/Components/YCbCrImage.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegConstants.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegDecoder.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegEncoder.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegFormat.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/JpegSubsample.cs delete mode 100644 src/ImageSharp46/Formats/Jpg/README.md delete mode 100644 src/ImageSharp46/Formats/Png/Filters/AverageFilter.cs delete mode 100644 src/ImageSharp46/Formats/Png/Filters/FilterType.cs delete mode 100644 src/ImageSharp46/Formats/Png/Filters/NoneFilter.cs delete mode 100644 src/ImageSharp46/Formats/Png/Filters/PaethFilter.cs delete mode 100644 src/ImageSharp46/Formats/Png/Filters/SubFilter.cs delete mode 100644 src/ImageSharp46/Formats/Png/Filters/UpFilter.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngChunk.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngChunkTypes.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngColorType.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngDecoder.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngDecoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngEncoder.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngEncoderCore.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngFormat.cs delete mode 100644 src/ImageSharp46/Formats/Png/PngHeader.cs delete mode 100644 src/ImageSharp46/Formats/Png/README.md delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/Adler32.cs delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/Crc32.cs delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/IChecksum.cs delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/README.md delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/ZlibDeflateStream.cs delete mode 100644 src/ImageSharp46/Formats/Png/Zlib/ZlibInflateStream.cs delete mode 100644 src/ImageSharp46/IO/BigEndianBitConverter.cs delete mode 100644 src/ImageSharp46/IO/EndianBinaryReader.cs delete mode 100644 src/ImageSharp46/IO/EndianBinaryWriter.cs delete mode 100644 src/ImageSharp46/IO/EndianBitConverter.cs delete mode 100644 src/ImageSharp46/IO/Endianness.cs delete mode 100644 src/ImageSharp46/IO/LittleEndianBitConverter.cs delete mode 100644 src/ImageSharp46/Image.cs delete mode 100644 src/ImageSharp46/Image/IImageBase.cs delete mode 100644 src/ImageSharp46/Image/IImageFrame.cs delete mode 100644 src/ImageSharp46/Image/IImageProcessor.cs delete mode 100644 src/ImageSharp46/Image/Image.cs delete mode 100644 src/ImageSharp46/Image/ImageBase.cs delete mode 100644 src/ImageSharp46/Image/ImageFrame.cs delete mode 100644 src/ImageSharp46/Image/ImageIOExtensions.cs delete mode 100644 src/ImageSharp46/Image/ImageProcessingExtensions.cs delete mode 100644 src/ImageSharp46/Image/ImageProperty.cs delete mode 100644 src/ImageSharp46/Image/PixelAccessor.cs delete mode 100644 src/ImageSharp46/Image/PixelRow.cs delete mode 100644 src/ImageSharp46/ImageProcessor.cs delete mode 100644 src/ImageSharp46/ImageSharp46.csproj delete mode 100644 src/ImageSharp46/Numerics/Ellipse.cs delete mode 100644 src/ImageSharp46/Numerics/LongRational.cs delete mode 100644 src/ImageSharp46/Numerics/Point.cs delete mode 100644 src/ImageSharp46/Numerics/Rational.cs delete mode 100644 src/ImageSharp46/Numerics/Rectangle.cs delete mode 100644 src/ImageSharp46/Numerics/SignedRational.cs delete mode 100644 src/ImageSharp46/Numerics/Size.cs delete mode 100644 src/ImageSharp46/PixelAccessor.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifDataType.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifParts.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifProfile.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifReader.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifTag.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifTagDescriptionAttribute.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifValue.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/ExifWriter.cs delete mode 100644 src/ImageSharp46/Profiles/Exif/README.md delete mode 100644 src/ImageSharp46/ProgressEventArgs.cs delete mode 100644 src/ImageSharp46/Properties/AssemblyInfo.cs delete mode 100644 src/ImageSharp46/Quantizers/IQuantizer.cs delete mode 100644 src/ImageSharp46/Quantizers/Octree/OctreeQuantizer.cs delete mode 100644 src/ImageSharp46/Quantizers/Octree/Quantizer.cs delete mode 100644 src/ImageSharp46/Quantizers/Options/Quantization.cs delete mode 100644 src/ImageSharp46/Quantizers/Palette/PaletteQuantizer.cs delete mode 100644 src/ImageSharp46/Quantizers/Quantize.cs delete mode 100644 src/ImageSharp46/Quantizers/QuantizedImage.cs delete mode 100644 src/ImageSharp46/Quantizers/Wu/Box.cs delete mode 100644 src/ImageSharp46/Quantizers/Wu/WuQuantizer.cs delete mode 100644 src/ImageSharp46/Samplers/AutoOrient.cs delete mode 100644 src/ImageSharp46/Samplers/BoxBlur.cs delete mode 100644 src/ImageSharp46/Samplers/Crop.cs delete mode 100644 src/ImageSharp46/Samplers/DetectEdges.cs delete mode 100644 src/ImageSharp46/Samplers/EntropyCrop.cs delete mode 100644 src/ImageSharp46/Samplers/Flip.cs delete mode 100644 src/ImageSharp46/Samplers/GuassianBlur.cs delete mode 100644 src/ImageSharp46/Samplers/GuassianSharpen.cs delete mode 100644 src/ImageSharp46/Samplers/OilPainting.cs delete mode 100644 src/ImageSharp46/Samplers/Options/AnchorPosition.cs delete mode 100644 src/ImageSharp46/Samplers/Options/FlipType.cs delete mode 100644 src/ImageSharp46/Samplers/Options/Orientation.cs delete mode 100644 src/ImageSharp46/Samplers/Options/ResizeHelper.cs delete mode 100644 src/ImageSharp46/Samplers/Options/ResizeMode.cs delete mode 100644 src/ImageSharp46/Samplers/Options/ResizeOptions.cs delete mode 100644 src/ImageSharp46/Samplers/Options/RotateType.cs delete mode 100644 src/ImageSharp46/Samplers/Pad.cs delete mode 100644 src/ImageSharp46/Samplers/Pixelate.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/CompandingResizeProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/BoxBlurProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/Convolution2DFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/Convolution2PassFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/ConvolutionFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/GuassianBlurProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Convolution/GuassianSharpenProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/CropProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/EntropyCropProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/FlipProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/IImageSampler.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/ImageSampler.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/Matrix3x2Processor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/OilPaintingProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/PixelateProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/ResamplingWeightedProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/ResizeProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/RotateProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Processors/SkewProcessor.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/BicubicResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/BoxResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/CatmullRomResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/HermiteResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/IResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/Lanczos2Resampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/Lanczos3Resampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/Lanczos5Resampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/Lanczos8Resampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/MitchellNetravaliResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/NearestNeighborResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/RobidouxResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/RobidouxSharpResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/SplineResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/TriangleResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resamplers/WelchResampler.cs delete mode 100644 src/ImageSharp46/Samplers/Resize.cs delete mode 100644 src/ImageSharp46/Samplers/Rotate.cs delete mode 100644 src/ImageSharp46/Samplers/RotateFlip.cs delete mode 100644 src/ImageSharp46/Samplers/Skew.cs delete mode 100644 src/ImageSharp46/app.config delete mode 100644 src/ImageSharp46/packages.config delete mode 100644 tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs delete mode 100644 tests/ImageSharp.Tests46/Colors/ColorConversionTests.cs delete mode 100644 tests/ImageSharp.Tests46/Colors/ColorTests.cs delete mode 100644 tests/ImageSharp.Tests46/DctSandbox.cs delete mode 100644 tests/ImageSharp.Tests46/FileTestBase.cs delete mode 100644 tests/ImageSharp.Tests46/Formats/Bmp/BitmapTests.cs delete mode 100644 tests/ImageSharp.Tests46/Formats/GeneralFormatTests.cs delete mode 100644 tests/ImageSharp.Tests46/Formats/Jpg/JpegTests.cs delete mode 100644 tests/ImageSharp.Tests46/Formats/Png/PngTests.cs delete mode 100644 tests/ImageSharp.Tests46/Helpers/GuardTests.cs delete mode 100644 tests/ImageSharp.Tests46/Image/ImagePropertyTests.cs delete mode 100644 tests/ImageSharp.Tests46/Image/PixelAccessorTests.cs delete mode 100644 tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj delete mode 100644 tests/ImageSharp.Tests46/Numerics/PointTests.cs delete mode 100644 tests/ImageSharp.Tests46/Numerics/RationalTests.cs delete mode 100644 tests/ImageSharp.Tests46/Numerics/RectangleTests.cs delete mode 100644 tests/ImageSharp.Tests46/Numerics/SignedRationalTests.cs delete mode 100644 tests/ImageSharp.Tests46/Numerics/SizeTests.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/AlphaTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BackgroundColorTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BinaryThreshold.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BlackWhiteTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BlendTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BoxBlurTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/BrightnessTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/ColorBlindnessTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/ContrastTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/GlowTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/GrayscaleTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/HueTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/InvertTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/KodachromeTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/LomographTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/PolaroidTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/SaturationTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/SepiaTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Filters/VignetteTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/AutoOrientTests.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/CropTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/DetectEdgesTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/EntropyCropTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/FlipTests.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/GuassianBlurTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/GuassianSharpenTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/OilPaintTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/PadTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/PixelateTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/ResizeTests.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/RotateFlipTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/RotateTest.cs delete mode 100644 tests/ImageSharp.Tests46/Processors/Samplers/SkewTest.cs delete mode 100644 tests/ImageSharp.Tests46/Profiles/Exif/ExifProfileTests.cs delete mode 100644 tests/ImageSharp.Tests46/Profiles/Exif/ExifTagDescriptionAttributeTests.cs delete mode 100644 tests/ImageSharp.Tests46/Profiles/Exif/ExifValueTests.cs delete mode 100644 tests/ImageSharp.Tests46/Properties/AssemblyInfo.cs delete mode 100644 tests/ImageSharp.Tests46/TestFile.cs delete mode 100644 tests/ImageSharp.Tests46/TestImages.cs delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Bmp/Car.bmp delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Bmp/F.bmp delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Bmp/neg_height.bmp delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Gif/giphy.gif delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Gif/rings.gif delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Calliphora.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Floorplan.jpeg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/cmyk.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/exif.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/fb.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/geneserath.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/progress.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Jpg/turtle.jpg delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Png/blur.png delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Png/indexed.png delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Png/pd.png delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Png/pl.png delete mode 100644 tests/ImageSharp.Tests46/TestImages/Formats/Png/splash.png delete mode 100644 tests/ImageSharp.Tests46/app.config delete mode 100644 tests/ImageSharp.Tests46/packages.config diff --git a/ImageSharp.46.sln b/ImageSharp.46.sln deleted file mode 100644 index 270d391cc..000000000 --- a/ImageSharp.46.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp46", "src\ImageSharp46\ImageSharp46.csproj", "{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Tests46", "tests\ImageSharp.Tests46\ImageSharp.Tests46.csproj", "{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleBenchmark", "tests\ConsoleBenchmark\ConsoleBenchmark.csproj", "{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Release|Any CPU.Build.0 = Release|Any CPU - {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.Build.0 = Release|Any CPU - {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/ImageSharp46/Bootstrapper.cs b/src/ImageSharp46/Bootstrapper.cs deleted file mode 100644 index 35a4a5225..000000000 --- a/src/ImageSharp46/Bootstrapper.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Threading.Tasks; - - using Formats; - - /// - /// Provides initialization code which allows extending the library. - /// - public class Bootstrapper - { - /// - /// A new instance Initializes a new instance of the class. - /// with lazy initialization. - /// - private static readonly Lazy Lazy = new Lazy(() => new Bootstrapper()); - - /// - /// The default list of supported - /// - private readonly List imageFormats; - - /// - /// Prevents a default instance of the class from being created. - /// - private Bootstrapper() - { - this.imageFormats = new List - { - new BmpFormat(), - new JpegFormat(), - new PngFormat(), - new GifFormat() - }; - } - - /// - /// Gets the current bootstrapper instance. - /// - public static Bootstrapper Instance => Lazy.Value; - - /// - /// Gets the collection of supported - /// - public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormats); - - /// - /// Gets or sets the global parallel options for processing tasks in parallel. - /// - public ParallelOptions ParallelOptions { get; set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; - - /// - /// Adds a new to the collection of supported image formats. - /// - /// The new format to add. - public void AddImageFormat(IImageFormat format) - { - this.imageFormats.Add(format); - } - } -} diff --git a/src/ImageSharp46/Colors/Color.cs b/src/ImageSharp46/Colors/Color.cs deleted file mode 100644 index c4ea2d762..000000000 --- a/src/ImageSharp46/Colors/Color.cs +++ /dev/null @@ -1,408 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Globalization; - using System.Numerics; - - /// - /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255. - /// The color components are stored in red, green, blue, and alpha order. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public partial struct Color : IPackedPixel, IEquatable - { - private const int RedShift = 0; - private const int GreenShift = 8; - private const int BlueShift = 16; - private const int AlphaShift = 24; - - /// - /// The maximum byte value. - /// - private static readonly Vector4 MaxBytes = new Vector4(255); - - /// - /// The half vector value. - /// - private static readonly Vector4 Half = new Vector4(0.5f); - - /// - /// The packed value. - /// - private uint packedValue; - - /// - /// Initializes a new instance of the struct. - /// - /// The red component. - /// The green component. - /// The blue component. - /// The alpha component. - public Color(byte r, byte g, byte b, byte a = 255) - { - this.packedValue = Pack(r, g, b, a); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The hexadecimal representation of the combined color components arranged - /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax. - /// - public Color(string hex) - { - Guard.NotNullOrEmpty(hex, nameof(hex)); - - hex = ToRgbaHex(hex); - - if (hex == null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out this.packedValue)) - { - throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); - } - - // Order parsed from hex string will be backwards, so reverse it. - this.packedValue = Pack(this.A, this.B, this.G, this.R); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red component. - /// The green component. - /// The blue component. - /// The alpha component. - public Color(float r, float g, float b, float a = 1) - { - this.packedValue = Pack(r, g, b, a); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector containing the components for the packed vector. - /// - public Color(Vector3 vector) - { - this.packedValue = Pack(ref vector); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector containing the components for the packed vector. - /// - public Color(Vector4 vector) - { - this.packedValue = Pack(ref vector); - } - - /// - /// Gets or sets the red component. - /// - public byte R - { - get - { - return (byte)(this.packedValue >> RedShift); - } - - set - { - this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift; - } - } - - /// - /// Gets or sets the green component. - /// - public byte G - { - get - { - return (byte)(this.packedValue >> GreenShift); - } - - set - { - this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift; - } - } - - /// - /// Gets or sets the blue component. - /// - public byte B - { - get - { - return (byte)(this.packedValue >> BlueShift); - } - - set - { - this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift; - } - } - - /// - /// Gets or sets the alpha component. - /// - public byte A - { - get - { - return (byte)(this.packedValue >> AlphaShift); - } - - set - { - this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift; - } - } - - /// - public uint PackedValue - { - get - { - return this.packedValue; - } - - set - { - this.packedValue = value; - } - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the parameter is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Color left, Color right) - { - return left.packedValue == right.packedValue; - } - - /// - /// Compares two objects for equality. - /// - /// The on the left side of the operand. - /// The on the right side of the operand. - /// - /// True if the parameter is equal to the parameter; otherwise, false. - /// - public static bool operator !=(Color left, Color right) - { - return left.packedValue != right.packedValue; - } - - /// - /// Creates a new instance of the struct. - /// - /// - /// The hexadecimal representation of the combined color components arranged - /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax. - /// - /// - /// The . - /// - public static Color FromHex(string hex) - { - return new Color(hex); - } - - /// - public void PackFromBytes(byte x, byte y, byte z, byte w) - { - this.packedValue = Pack(x, y, z, w); - } - - /// - /// Converts the value of this instance to a hexadecimal string. - /// - /// A hexadecimal string representation of the value. - public string ToHex() - { - uint hexOrder = Pack(this.A, this.B, this.G, this.R); - return hexOrder.ToString("X8"); - } - - /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) - { - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - bytes[startIndex + 3] = this.A; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - bytes[startIndex + 3] = this.A; - break; - default: - throw new NotSupportedException(); - } - } - - /// - public void PackFromVector4(Vector4 vector) - { - this.packedValue = Pack(ref vector); - } - - /// - public Vector4 ToVector4() - { - return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes; - } - - /// - public override bool Equals(object obj) - { - return (obj is Color) && this.Equals((Color)obj); - } - - /// - public bool Equals(Color other) - { - return this.packedValue == other.packedValue; - } - - /// - /// Gets a string representation of the packed vector. - /// - /// A string representation of the packed vector. - public override string ToString() - { - return this.ToVector4().ToString(); - } - - /// - public override int GetHashCode() - { - return this.packedValue.GetHashCode(); - } - - /// - /// Packs a into a uint. - /// - /// The vector containing the values to pack. - /// The containing the packed values. - private static uint Pack(ref Vector4 vector) - { - vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One); - vector *= MaxBytes; - vector += Half; - return (uint)(((byte)vector.X << RedShift) - | ((byte)vector.Y << GreenShift) - | ((byte)vector.Z << BlueShift) - | (byte)vector.W << AlphaShift); - } - - /// - /// Packs a into a uint. - /// - /// The vector containing the values to pack. - /// The containing the packed values. - private static uint Pack(ref Vector3 vector) - { - Vector4 value = new Vector4(vector, 1); - return Pack(ref value); - } - - /// - /// Packs the four floats into a . - /// - /// The x-component - /// The y-component - /// The z-component - /// The w-component - /// The - private static uint Pack(float x, float y, float z, float w) - { - Vector4 value = new Vector4(x, y, z, w); - return Pack(ref value); - } - - /// - /// Packs the four floats into a . - /// - /// The x-component - /// The y-component - /// The z-component - /// The w-component - /// The - private static uint Pack(byte x, byte y, byte z, byte w) - { - return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift); - } - - /// - /// Converts the specified hex value to an rrggbbaa hex value. - /// - /// The hex value to convert. - /// - /// A rrggbbaa hex value. - /// - private static string ToRgbaHex(string hex) - { - hex = hex.StartsWith("#") ? hex.Substring(1) : hex; - - if (hex.Length == 8) - { - return hex; - } - - if (hex.Length == 6) - { - return hex + "FF"; - } - - if (hex.Length < 3 || hex.Length > 4) - { - return null; - } - - string red = char.ToString(hex[0]); - string green = char.ToString(hex[1]); - string blue = char.ToString(hex[2]); - string alpha = hex.Length == 3 ? "F" : char.ToString(hex[3]); - - return red + red + green + green + blue + blue + alpha + alpha; - } - } -} diff --git a/src/ImageSharp46/Colors/ColorConstants.cs b/src/ImageSharp46/Colors/ColorConstants.cs deleted file mode 100644 index f3b01f466..000000000 --- a/src/ImageSharp46/Colors/ColorConstants.cs +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - - /// - /// Provides useful color definitions. - /// - public static class ColorConstants - { - /// - /// Provides a lazy, one time method of returning the colors. - /// - private static readonly Lazy SafeColors = new Lazy(GetWebSafeColors); - - /// - /// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4. - /// - public static Color[] WebSafeColors => SafeColors.Value; - - /// - /// Returns an array of web safe colors. - /// - /// - private static Color[] GetWebSafeColors() - { - return new List - { - Color.AliceBlue, - Color.AntiqueWhite, - Color.Aqua, - Color.Aquamarine, - Color.Azure, - Color.Beige, - Color.Bisque, - Color.Black, - Color.BlanchedAlmond, - Color.Blue, - Color.BlueViolet, - Color.Brown, - Color.BurlyWood, - Color.CadetBlue, - Color.Chartreuse, - Color.Chocolate, - Color.Coral, - Color.CornflowerBlue, - Color.Cornsilk, - Color.Crimson, - Color.Cyan, - Color.DarkBlue, - Color.DarkCyan, - Color.DarkGoldenrod, - Color.DarkGray, - Color.DarkGreen, - Color.DarkKhaki, - Color.DarkMagenta, - Color.DarkOliveGreen, - Color.DarkOrange, - Color.DarkOrchid, - Color.DarkRed, - Color.DarkSalmon, - Color.DarkSeaGreen, - Color.DarkSlateBlue, - Color.DarkSlateGray, - Color.DarkTurquoise, - Color.DarkViolet, - Color.DeepPink, - Color.DeepSkyBlue, - Color.DimGray, - Color.DodgerBlue, - Color.Firebrick, - Color.FloralWhite, - Color.ForestGreen, - Color.Fuchsia, - Color.Gainsboro, - Color.GhostWhite, - Color.Gold, - Color.Goldenrod, - Color.Gray, - Color.Green, - Color.GreenYellow, - Color.Honeydew, - Color.HotPink, - Color.IndianRed, - Color.Indigo, - Color.Ivory, - Color.Khaki, - Color.Lavender, - Color.LavenderBlush, - Color.LawnGreen, - Color.LemonChiffon, - Color.LightBlue, - Color.LightCoral, - Color.LightCyan, - Color.LightGoldenrodYellow, - Color.LightGray, - Color.LightGreen, - Color.LightPink, - Color.LightSalmon, - Color.LightSeaGreen, - Color.LightSkyBlue, - Color.LightSlateGray, - Color.LightSteelBlue, - Color.LightYellow, - Color.Lime, - Color.LimeGreen, - Color.Linen, - Color.Magenta, - Color.Maroon, - Color.MediumAquamarine, - Color.MediumBlue, - Color.MediumOrchid, - Color.MediumPurple, - Color.MediumSeaGreen, - Color.MediumSlateBlue, - Color.MediumSpringGreen, - Color.MediumTurquoise, - Color.MediumVioletRed, - Color.MidnightBlue, - Color.MintCream, - Color.MistyRose, - Color.Moccasin, - Color.NavajoWhite, - Color.Navy, - Color.OldLace, - Color.Olive, - Color.OliveDrab, - Color.Orange, - Color.OrangeRed, - Color.Orchid, - Color.PaleGoldenrod, - Color.PaleGreen, - Color.PaleTurquoise, - Color.PaleVioletRed, - Color.PapayaWhip, - Color.PeachPuff, - Color.Peru, - Color.Pink, - Color.Plum, - Color.PowderBlue, - Color.Purple, - Color.RebeccaPurple, - Color.Red, - Color.RosyBrown, - Color.RoyalBlue, - Color.SaddleBrown, - Color.Salmon, - Color.SandyBrown, - Color.SeaGreen, - Color.SeaShell, - Color.Sienna, - Color.Silver, - Color.SkyBlue, - Color.SlateBlue, - Color.SlateGray, - Color.Snow, - Color.SpringGreen, - Color.SteelBlue, - Color.Tan, - Color.Teal, - Color.Thistle, - Color.Tomato, - Color.Transparent, - Color.Turquoise, - Color.Violet, - Color.Wheat, - Color.White, - Color.WhiteSmoke, - Color.Yellow, - Color.YellowGreen - }.ToArray(); - } - } -} diff --git a/src/ImageSharp46/Colors/ColorDefinitions.cs b/src/ImageSharp46/Colors/ColorDefinitions.cs deleted file mode 100644 index 46e0f8709..000000000 --- a/src/ImageSharp46/Colors/ColorDefinitions.cs +++ /dev/null @@ -1,728 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255. - /// The color components are stored in red, green, blue, and alpha order. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public partial struct Color - { - /// - /// Represents a matching the W3C definition that has an hex value of #F0F8FF. - /// - public static readonly Color AliceBlue = new Color(240, 248, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAEBD7. - /// - public static readonly Color AntiqueWhite = new Color(250, 235, 215, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FFFF. - /// - public static readonly Color Aqua = new Color(0, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7FFFD4. - /// - public static readonly Color Aquamarine = new Color(127, 255, 212, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0FFFF. - /// - public static readonly Color Azure = new Color(240, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5F5DC. - /// - public static readonly Color Beige = new Color(245, 245, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4C4. - /// - public static readonly Color Bisque = new Color(255, 228, 196, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #000000. - /// - public static readonly Color Black = new Color(0, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFEBCD. - /// - public static readonly Color BlanchedAlmond = new Color(255, 235, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #0000FF. - /// - public static readonly Color Blue = new Color(0, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8A2BE2. - /// - public static readonly Color BlueViolet = new Color(138, 43, 226, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A52A2A. - /// - public static readonly Color Brown = new Color(165, 42, 42, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DEB887. - /// - public static readonly Color BurlyWood = new Color(222, 184, 135, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #5F9EA0. - /// - public static readonly Color CadetBlue = new Color(95, 158, 160, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7FFF00. - /// - public static readonly Color Chartreuse = new Color(127, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D2691E. - /// - public static readonly Color Chocolate = new Color(210, 105, 30, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF7F50. - /// - public static readonly Color Coral = new Color(255, 127, 80, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6495ED. - /// - public static readonly Color CornflowerBlue = new Color(100, 149, 237, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF8DC. - /// - public static readonly Color Cornsilk = new Color(255, 248, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DC143C. - /// - public static readonly Color Crimson = new Color(220, 20, 60, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FFFF. - /// - public static readonly Color Cyan = new Color(0, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00008B. - /// - public static readonly Color DarkBlue = new Color(0, 0, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008B8B. - /// - public static readonly Color DarkCyan = new Color(0, 139, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B8860B. - /// - public static readonly Color DarkGoldenrod = new Color(184, 134, 11, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A9A9A9. - /// - public static readonly Color DarkGray = new Color(169, 169, 169, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #006400. - /// - public static readonly Color DarkGreen = new Color(0, 100, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BDB76B. - /// - public static readonly Color DarkKhaki = new Color(189, 183, 107, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B008B. - /// - public static readonly Color DarkMagenta = new Color(139, 0, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #556B2F. - /// - public static readonly Color DarkOliveGreen = new Color(85, 107, 47, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF8C00. - /// - public static readonly Color DarkOrange = new Color(255, 140, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9932CC. - /// - public static readonly Color DarkOrchid = new Color(153, 50, 204, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B0000. - /// - public static readonly Color DarkRed = new Color(139, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E9967A. - /// - public static readonly Color DarkSalmon = new Color(233, 150, 122, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8FBC8B. - /// - public static readonly Color DarkSeaGreen = new Color(143, 188, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #483D8B. - /// - public static readonly Color DarkSlateBlue = new Color(72, 61, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #2F4F4F. - /// - public static readonly Color DarkSlateGray = new Color(47, 79, 79, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00CED1. - /// - public static readonly Color DarkTurquoise = new Color(0, 206, 209, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9400D3. - /// - public static readonly Color DarkViolet = new Color(148, 0, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF1493. - /// - public static readonly Color DeepPink = new Color(255, 20, 147, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00BFFF. - /// - public static readonly Color DeepSkyBlue = new Color(0, 191, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #696969. - /// - public static readonly Color DimGray = new Color(105, 105, 105, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #1E90FF. - /// - public static readonly Color DodgerBlue = new Color(30, 144, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B22222. - /// - public static readonly Color Firebrick = new Color(178, 34, 34, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFAF0. - /// - public static readonly Color FloralWhite = new Color(255, 250, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #228B22. - /// - public static readonly Color ForestGreen = new Color(34, 139, 34, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF00FF. - /// - public static readonly Color Fuchsia = new Color(255, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DCDCDC. - /// - public static readonly Color Gainsboro = new Color(220, 220, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F8F8FF. - /// - public static readonly Color GhostWhite = new Color(248, 248, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFD700. - /// - public static readonly Color Gold = new Color(255, 215, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DAA520. - /// - public static readonly Color Goldenrod = new Color(218, 165, 32, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #808080. - /// - public static readonly Color Gray = new Color(128, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008000. - /// - public static readonly Color Green = new Color(0, 128, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #ADFF2F. - /// - public static readonly Color GreenYellow = new Color(173, 255, 47, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0FFF0. - /// - public static readonly Color Honeydew = new Color(240, 255, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF69B4. - /// - public static readonly Color HotPink = new Color(255, 105, 180, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #CD5C5C. - /// - public static readonly Color IndianRed = new Color(205, 92, 92, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4B0082. - /// - public static readonly Color Indigo = new Color(75, 0, 130, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFF0. - /// - public static readonly Color Ivory = new Color(255, 255, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0E68C. - /// - public static readonly Color Khaki = new Color(240, 230, 140, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E6E6FA. - /// - public static readonly Color Lavender = new Color(230, 230, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF0F5. - /// - public static readonly Color LavenderBlush = new Color(255, 240, 245, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7CFC00. - /// - public static readonly Color LawnGreen = new Color(124, 252, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFACD. - /// - public static readonly Color LemonChiffon = new Color(255, 250, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #ADD8E6. - /// - public static readonly Color LightBlue = new Color(173, 216, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F08080. - /// - public static readonly Color LightCoral = new Color(240, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E0FFFF. - /// - public static readonly Color LightCyan = new Color(224, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAFAD2. - /// - public static readonly Color LightGoldenrodYellow = new Color(250, 250, 210, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D3D3D3. - /// - public static readonly Color LightGray = new Color(211, 211, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #90EE90. - /// - public static readonly Color LightGreen = new Color(144, 238, 144, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFB6C1. - /// - public static readonly Color LightPink = new Color(255, 182, 193, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFA07A. - /// - public static readonly Color LightSalmon = new Color(255, 160, 122, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #20B2AA. - /// - public static readonly Color LightSeaGreen = new Color(32, 178, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #87CEFA. - /// - public static readonly Color LightSkyBlue = new Color(135, 206, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #778899. - /// - public static readonly Color LightSlateGray = new Color(119, 136, 153, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B0C4DE. - /// - public static readonly Color LightSteelBlue = new Color(176, 196, 222, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFE0. - /// - public static readonly Color LightYellow = new Color(255, 255, 224, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FF00. - /// - public static readonly Color Lime = new Color(0, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #32CD32. - /// - public static readonly Color LimeGreen = new Color(50, 205, 50, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAF0E6. - /// - public static readonly Color Linen = new Color(250, 240, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF00FF. - /// - public static readonly Color Magenta = new Color(255, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #800000. - /// - public static readonly Color Maroon = new Color(128, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #66CDAA. - /// - public static readonly Color MediumAquamarine = new Color(102, 205, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #0000CD. - /// - public static readonly Color MediumBlue = new Color(0, 0, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BA55D3. - /// - public static readonly Color MediumOrchid = new Color(186, 85, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9370DB. - /// - public static readonly Color MediumPurple = new Color(147, 112, 219, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #3CB371. - /// - public static readonly Color MediumSeaGreen = new Color(60, 179, 113, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7B68EE. - /// - public static readonly Color MediumSlateBlue = new Color(123, 104, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FA9A. - /// - public static readonly Color MediumSpringGreen = new Color(0, 250, 154, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #48D1CC. - /// - public static readonly Color MediumTurquoise = new Color(72, 209, 204, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #C71585. - /// - public static readonly Color MediumVioletRed = new Color(199, 21, 133, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #191970. - /// - public static readonly Color MidnightBlue = new Color(25, 25, 112, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5FFFA. - /// - public static readonly Color MintCream = new Color(245, 255, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4E1. - /// - public static readonly Color MistyRose = new Color(255, 228, 225, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4B5. - /// - public static readonly Color Moccasin = new Color(255, 228, 181, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFDEAD. - /// - public static readonly Color NavajoWhite = new Color(255, 222, 173, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #000080. - /// - public static readonly Color Navy = new Color(0, 0, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FDF5E6. - /// - public static readonly Color OldLace = new Color(253, 245, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #808000. - /// - public static readonly Color Olive = new Color(128, 128, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6B8E23. - /// - public static readonly Color OliveDrab = new Color(107, 142, 35, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFA500. - /// - public static readonly Color Orange = new Color(255, 165, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF4500. - /// - public static readonly Color OrangeRed = new Color(255, 69, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DA70D6. - /// - public static readonly Color Orchid = new Color(218, 112, 214, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #EEE8AA. - /// - public static readonly Color PaleGoldenrod = new Color(238, 232, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #98FB98. - /// - public static readonly Color PaleGreen = new Color(152, 251, 152, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #AFEEEE. - /// - public static readonly Color PaleTurquoise = new Color(175, 238, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DB7093. - /// - public static readonly Color PaleVioletRed = new Color(219, 112, 147, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFEFD5. - /// - public static readonly Color PapayaWhip = new Color(255, 239, 213, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFDAB9. - /// - public static readonly Color PeachPuff = new Color(255, 218, 185, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #CD853F. - /// - public static readonly Color Peru = new Color(205, 133, 63, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFC0CB. - /// - public static readonly Color Pink = new Color(255, 192, 203, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DDA0DD. - /// - public static readonly Color Plum = new Color(221, 160, 221, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B0E0E6. - /// - public static readonly Color PowderBlue = new Color(176, 224, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #800080. - /// - public static readonly Color Purple = new Color(128, 0, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #0. - /// - public static readonly Color RebeccaPurple = new Color(102, 51, 153, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF0000. - /// - public static readonly Color Red = new Color(255, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BC8F8F. - /// - public static readonly Color RosyBrown = new Color(188, 143, 143, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4169E1. - /// - public static readonly Color RoyalBlue = new Color(65, 105, 225, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B4513. - /// - public static readonly Color SaddleBrown = new Color(139, 69, 19, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FA8072. - /// - public static readonly Color Salmon = new Color(250, 128, 114, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F4A460. - /// - public static readonly Color SandyBrown = new Color(244, 164, 96, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #2E8B57. - /// - public static readonly Color SeaGreen = new Color(46, 139, 87, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF5EE. - /// - public static readonly Color SeaShell = new Color(255, 245, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A0522D. - /// - public static readonly Color Sienna = new Color(160, 82, 45, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #C0C0C0. - /// - public static readonly Color Silver = new Color(192, 192, 192, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #87CEEB. - /// - public static readonly Color SkyBlue = new Color(135, 206, 235, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6A5ACD. - /// - public static readonly Color SlateBlue = new Color(106, 90, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #708090. - /// - public static readonly Color SlateGray = new Color(112, 128, 144, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFAFA. - /// - public static readonly Color Snow = new Color(255, 250, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FF7F. - /// - public static readonly Color SpringGreen = new Color(0, 255, 127, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4682B4. - /// - public static readonly Color SteelBlue = new Color(70, 130, 180, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D2B48C. - /// - public static readonly Color Tan = new Color(210, 180, 140, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008080. - /// - public static readonly Color Teal = new Color(0, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D8BFD8. - /// - public static readonly Color Thistle = new Color(216, 191, 216, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF6347. - /// - public static readonly Color Tomato = new Color(255, 99, 71, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFFF. - /// - public static readonly Color Transparent = new Color(255, 255, 255, 0); - - /// - /// Represents a matching the W3C definition that has an hex value of #40E0D0. - /// - public static readonly Color Turquoise = new Color(64, 224, 208, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #EE82EE. - /// - public static readonly Color Violet = new Color(238, 130, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5DEB3. - /// - public static readonly Color Wheat = new Color(245, 222, 179, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFFF. - /// - public static readonly Color White = new Color(255, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5F5F5. - /// - public static readonly Color WhiteSmoke = new Color(245, 245, 245, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFF00. - /// - public static readonly Color Yellow = new Color(255, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9ACD32. - /// - public static readonly Color YellowGreen = new Color(154, 205, 50, 255); - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Colors/ColorTransforms.cs b/src/ImageSharp46/Colors/ColorTransforms.cs deleted file mode 100644 index e710b69e9..000000000 --- a/src/ImageSharp46/Colors/ColorTransforms.cs +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Numerics; - - /// - /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255. - /// The color components are stored in red, green, blue, and alpha order. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public partial struct Color - { - /// - /// Blends two colors by multiplication. - /// - /// The source color is multiplied by the destination color and replaces the destination. - /// The resultant color is always at least as dark as either the source or destination color. - /// Multiplying any color with black results in black. Multiplying any color with white preserves the - /// original color. - /// - /// - /// The source color. - /// The destination color. - /// - /// The . - /// - public static Color Multiply(Color source, Color destination) - { - if (destination == Color.Black) - { - return Color.Black; - } - - if (destination == Color.White) - { - return source; - } - - // TODO: This will use less memory than using Vector4 - // but we should test speed vs memory to see which is best balance. - byte r = (byte)(source.R * destination.R).Clamp(0, 255); - byte g = (byte)(source.G * destination.G).Clamp(0, 255); - byte b = (byte)(source.B * destination.B).Clamp(0, 255); - byte a = (byte)(source.A * destination.A).Clamp(0, 255); - - return new Color(r, g, b, a); - } - - /// - /// Linearly interpolates from one color to another based on the given weighting. - /// - /// The first color value. - /// The second color value. - /// - /// A value between 0 and 1 indicating the weight of the second source vector. - /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. - /// - /// - /// The - /// - public static Color Lerp(Color from, Color to, float amount) - { - return new Color(Vector4.Lerp(from.ToVector4(), to.ToVector4(), amount)); - } - } -} diff --git a/src/ImageSharp46/Colors/ColorspaceTransforms.cs b/src/ImageSharp46/Colors/ColorspaceTransforms.cs deleted file mode 100644 index 0c70dd98b..000000000 --- a/src/ImageSharp46/Colors/ColorspaceTransforms.cs +++ /dev/null @@ -1,292 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Numerics; - - /// - /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255. - /// The color components are stored in red, green, blue, and alpha order. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public partial struct Color - { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Bgra32 color) - { - return new Color(color.R, color.G, color.B, color.A); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Cmyk cmykColor) - { - float r = (1 - cmykColor.C) * (1 - cmykColor.K); - float g = (1 - cmykColor.M) * (1 - cmykColor.K); - float b = (1 - cmykColor.Y) * (1 - cmykColor.K); - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(YCbCr color) - { - byte y = color.Y; - int cb = color.Cb - 128; - int cr = color.Cr - 128; - - byte r = (byte)(y + (1.402F * cr)).Clamp(0, 255); - byte g = (byte)(y - (0.34414F * cb) - (0.71414F * cr)).Clamp(0, 255); - byte b = (byte)(y + (1.772F * cb)).Clamp(0, 255); - - return new Color(r, g, b); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(CieXyz color) - { - float x = color.X / 100F; - float y = color.Y / 100F; - float z = color.Z / 100F; - - // Then XYZ to RGB (multiplication by 100 was done above already) - float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); - float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); - float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); - - Vector4 vector = new Vector4(r, g, b, 1).Compress(); - return new Color(vector); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Hsv color) - { - float s = color.S; - float v = color.V; - - if (Math.Abs(s) < Epsilon) - { - return new Color(v, v, v, 1); - } - - float h = (Math.Abs(color.H - 360) < Epsilon) ? 0 : color.H / 60; - int i = (int)Math.Truncate(h); - float f = h - i; - - float p = v * (1.0F - s); - float q = v * (1.0F - (s * f)); - float t = v * (1.0F - (s * (1.0F - f))); - - float r, g, b; - switch (i) - { - case 0: - r = v; - g = t; - b = p; - break; - - case 1: - r = q; - g = v; - b = p; - break; - - case 2: - r = p; - g = v; - b = t; - break; - - case 3: - r = p; - g = q; - b = v; - break; - - case 4: - r = t; - g = p; - b = v; - break; - - default: - r = v; - g = p; - b = q; - break; - } - - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Hsl color) - { - float rangedH = color.H / 360F; - float r = 0; - float g = 0; - float b = 0; - float s = color.S; - float l = color.L; - - if (Math.Abs(l) > Epsilon) - { - if (Math.Abs(s) < Epsilon) - { - r = g = b = l; - } - else - { - float temp2 = (l < 0.5f) ? l * (1f + s) : l + s - (l * s); - float temp1 = (2f * l) - temp2; - - r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F); - g = GetColorComponent(temp1, temp2, rangedH); - b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F); - } - } - - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(CieLab cieLabColor) - { - // First convert back to XYZ... - float y = (cieLabColor.L + 16F) / 116F; - float x = (cieLabColor.A / 500F) + y; - float z = y - (cieLabColor.B / 200F); - - float x3 = x * x * x; - float y3 = y * y * y; - float z3 = z * z * z; - - x = x3 > 0.008856F ? x3 : (x - 0.137931F) / 7.787F; - y = (cieLabColor.L > 7.999625F) ? y3 : (cieLabColor.L / 903.3F); - z = (z3 > 0.008856F) ? z3 : (z - 0.137931F) / 7.787F; - - x *= 0.95047F; - z *= 1.08883F; - - // Then XYZ to RGB (multiplication by 100 was done above already) - float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); - float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); - float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); - - return new Color(new Vector4(r, g, b, 1F).Compress()); - } - - /// - /// Gets the color component from the given values. - /// - /// The first value. - /// The second value. - /// The third value. - /// - /// The . - /// - private static float GetColorComponent(float first, float second, float third) - { - third = MoveIntoRange(third); - if (third < 0.1666667F) - { - return first + ((second - first) * 6.0f * third); - } - - if (third < 0.5) - { - return second; - } - - if (third < 0.6666667F) - { - return first + ((second - first) * (0.6666667F - third) * 6.0f); - } - - return first; - } - - /// - /// Moves the specific value within the acceptable range for - /// conversion. - /// Used for converting colors to this type. - /// - /// The value to shift. - /// - /// The . - /// - private static float MoveIntoRange(float value) - { - if (value < 0.0) - { - value += 1.0f; - } - else if (value > 1.0) - { - value -= 1.0f; - } - - return value; - } - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/Bgra32.cs b/src/ImageSharp46/Colors/Colorspaces/Bgra32.cs deleted file mode 100644 index ff9203b03..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/Bgra32.cs +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an BGRA (blue, green, red, alpha) color. - /// - public struct Bgra32 : IEquatable - { - /// - /// Represents a 32 bit that has B, G, R, and A values set to zero. - /// - public static readonly Bgra32 Empty = default(Bgra32); - - /// - /// The backing vector for SIMD support. - /// - private Vector4 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The blue component of this . - /// The green component of this . - /// The red component of this . - /// The alpha component of this . - public Bgra32(byte b, byte g, byte r, byte a = 255) - : this() - { - this.backingVector = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, new Vector4(255)); - } - - /// - /// Gets the blue component of the color - /// - public byte B => (byte)this.backingVector.X; - - /// - /// Gets the green component of the color - /// - public byte G => (byte)this.backingVector.Y; - - /// - /// Gets the red component of the color - /// - public byte R => (byte)this.backingVector.Z; - - /// - /// Gets the alpha component of the color - /// - public byte A => (byte)this.backingVector.W; - - /// - /// Gets the integer representation of the color. - /// - public int Bgra => (this.R << 16) | (this.G << 8) | (this.B << 0) | (this.A << 24); - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator Bgra32(Color color) - { - return new Bgra32(color.B, color.G, color.R, color.A); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Bgra32 left, Bgra32 right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Bgra32 left, Bgra32 right) - { - return !left.Equals(right); - } - - /// - public override bool Equals(object obj) - { - if (obj is Bgra32) - { - Bgra32 color = (Bgra32)obj; - - return this.backingVector == color.backingVector; - } - - return false; - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Bgra32 [ Empty ]"; - } - - return $"Bgra32 [ B={this.B}, G={this.G}, R={this.R}, A={this.A} ]"; - } - - /// - public bool Equals(Bgra32 other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Bgra32 color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/CieLab.cs b/src/ImageSharp46/Colors/Colorspaces/CieLab.cs deleted file mode 100644 index b0c042a3c..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/CieLab.cs +++ /dev/null @@ -1,192 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CIE LAB 1976 color. - /// - /// - public struct CieLab : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has L, A, B values set to zero. - /// - public static readonly CieLab Empty = default(CieLab); - - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - - /// - /// The backing vector for SIMD support. - /// - private Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The lightness dimension. - /// The a (green - magenta) component. - /// The b (blue - yellow) component. - public CieLab(float l, float a, float b) - : this() - { - this.backingVector = Vector3.Clamp(new Vector3(l, a, b), new Vector3(0, -100, -100), new Vector3(100)); - } - - /// - /// Gets the lightness dimension. - /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public float L => this.backingVector.X; - - /// - /// Gets the a color component. - /// Negative is green, positive magenta. - /// - public float A => this.backingVector.Y; - - /// - /// Gets the b color component. - /// Negative is blue, positive is yellow - /// - public float B => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator CieLab(Color color) - { - // First convert to CIE XYZ - Vector4 vector = color.ToVector4().Expand(); - float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); - float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); - float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); - - // Now to LAB - x /= 0.95047F; - //y /= 1F; - z /= 1.08883F; - - x = x > 0.008856F ? (float)Math.Pow(x, 0.3333333F) : ((903.3F * x) + 16F) / 116F; - y = y > 0.008856F ? (float)Math.Pow(y, 0.3333333F) : ((903.3F * y) + 16F) / 116F; - z = z > 0.008856F ? (float)Math.Pow(z, 0.3333333F) : ((903.3F * z) + 16F) / 116F; - - float l = Math.Max(0, (116F * y) - 16F); - float a = 500F * (x - y); - float b = 200F * (y - z); - - return new CieLab(l, a, b); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(CieLab left, CieLab right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(CieLab left, CieLab right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "CieLab [Empty]"; - } - - return $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is CieLab) - { - return this.Equals((CieLab)obj); - } - - return false; - } - - /// - public bool Equals(CieLab other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(CieLab other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(CieLab color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/CieXyz.cs b/src/ImageSharp46/Colors/Colorspaces/CieXyz.cs deleted file mode 100644 index 8e9d5f796..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/CieXyz.cs +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CIE 1931 color - /// - /// - public struct CieXyz : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has Y, Cb, and Cr values set to zero. - /// - public static readonly CieXyz Empty = default(CieXyz); - - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - - /// - /// The backing vector for SIMD support. - /// - private Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The y luminance component. - /// X is a mix (a linear combination) of cone response curves chosen to be nonnegative - /// Z is quasi-equal to blue stimulation, or the S cone of the human eye. - public CieXyz(float x, float y, float z) - : this() - { - // Not clamping as documentation about this space seems to indicate "usual" ranges - this.backingVector = new Vector3(x, y, z); - } - - /// - /// Gets the Y luminance component. - /// A value ranging between 380 and 780. - /// - public float X => this.backingVector.X; - - /// - /// Gets the Cb chroma component. - /// A value ranging between 380 and 780. - /// - public float Y => this.backingVector.Y; - - /// - /// Gets the Cr chroma component. - /// A value ranging between 380 and 780. - /// - public float Z => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator CieXyz(Color color) - { - Vector4 vector = color.ToVector4().Expand(); - - float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); - float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); - float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); - - x *= 100F; - y *= 100F; - z *= 100F; - - return new CieXyz(x, y, z); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(CieXyz left, CieXyz right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(CieXyz left, CieXyz right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "CieXyz [ Empty ]"; - } - - return $"CieXyz [ X={this.X:#0.##}, Y={this.Y:#0.##}, Z={this.Z:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is CieXyz) - { - return this.Equals((CieXyz)obj); - } - - return false; - } - - /// - public bool Equals(CieXyz other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(CieXyz other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(CieXyz color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/Cmyk.cs b/src/ImageSharp46/Colors/Colorspaces/Cmyk.cs deleted file mode 100644 index 15bea263c..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/Cmyk.cs +++ /dev/null @@ -1,195 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CMYK (cyan, magenta, yellow, keyline) color. - /// - public struct Cmyk : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has C, M, Y, and K values set to zero. - /// - public static readonly Cmyk Empty = default(Cmyk); - - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - - /// - /// The backing vector for SIMD support. - /// - private Vector4 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The cyan component. - /// The magenta component. - /// The yellow component. - /// The keyline black component. - public Cmyk(float c, float m, float y, float k) - : this() - { - this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), Vector4.Zero, Vector4.One); - } - - /// - /// Gets the cyan color component. - /// A value ranging between 0 and 1. - /// - public float C => this.backingVector.X; - - /// - /// Gets the magenta color component. - /// A value ranging between 0 and 1. - /// - public float M => this.backingVector.Y; - - /// - /// Gets the yellow color component. - /// A value ranging between 0 and 1. - /// - public float Y => this.backingVector.Z; - - /// - /// Gets the keyline black color component. - /// A value ranging between 0 and 1. - /// - public float K => this.backingVector.W; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator Cmyk(Color color) - { - float c = 1f - (color.R / 255F); - float m = 1f - (color.G / 255F); - float y = 1f - (color.B / 255F); - - float k = Math.Min(c, Math.Min(m, y)); - - if (Math.Abs(k - 1.0f) <= Epsilon) - { - return new Cmyk(0, 0, 0, 1); - } - - c = (c - k) / (1 - k); - m = (m - k) / (1 - k); - y = (y - k) / (1 - k); - - return new Cmyk(c, m, y, k); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Cmyk left, Cmyk right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Cmyk left, Cmyk right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Cmyk [Empty]"; - } - - return $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Cmyk) - { - return this.Equals((Cmyk)obj); - } - - return false; - } - - /// - public bool Equals(Cmyk other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(Cmyk other, float precision) - { - Vector4 result = Vector4.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision - && result.W < precision; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Cmyk color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/Hsl.cs b/src/ImageSharp46/Colors/Colorspaces/Hsl.cs deleted file mode 100644 index 1cc54ec8c..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/Hsl.cs +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents a Hsl (hue, saturation, lightness) color. - /// - public struct Hsl : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has H, S, and L values set to zero. - /// - public static readonly Hsl Empty = default(Hsl); - - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - - /// - /// The backing vector for SIMD support. - /// - private Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The h hue component. - /// The s saturation component. - /// The l value (lightness) component. - public Hsl(float h, float s, float l) - { - this.backingVector = Vector3.Clamp(new Vector3(h, s, l), Vector3.Zero, new Vector3(360, 1, 1)); - } - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public float H => this.backingVector.X; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public float S => this.backingVector.Y; - - /// - /// Gets the lightness component. - /// A value ranging between 0 and 1. - /// - public float L => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Hsl(Color color) - { - float r = color.R / 255F; - float g = color.G / 255F; - float b = color.B / 255F; - - float max = Math.Max(r, Math.Max(g, b)); - float min = Math.Min(r, Math.Min(g, b)); - float chroma = max - min; - float h = 0; - float s = 0; - float l = (max + min) / 2; - - if (Math.Abs(chroma) < Epsilon) - { - return new Hsl(0, s, l); - } - - if (Math.Abs(r - max) < Epsilon) - { - h = (g - b) / chroma; - } - else if (Math.Abs(g - max) < Epsilon) - { - h = 2 + ((b - r) / chroma); - } - else if (Math.Abs(b - max) < Epsilon) - { - h = 4 + ((r - g) / chroma); - } - - h *= 60; - if (h < 0.0) - { - h += 360; - } - - if (l <= .5f) - { - s = chroma / (max + min); - } - else - { - s = chroma / (2 - chroma); - } - - return new Hsl(h, s, l); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Hsl left, Hsl right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Hsl left, Hsl right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Hsl [ Empty ]"; - } - - return $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Hsl) - { - return this.Equals((Hsl)obj); - } - - return false; - } - - /// - public bool Equals(Hsl other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(Hsl other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Hsl color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/Hsv.cs b/src/ImageSharp46/Colors/Colorspaces/Hsv.cs deleted file mode 100644 index b55e07e6b..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/Hsv.cs +++ /dev/null @@ -1,206 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness). - /// - public struct Hsv : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has H, S, and V values set to zero. - /// - public static readonly Hsv Empty = default(Hsv); - - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - - /// - /// The backing vector for SIMD support. - /// - private Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The h hue component. - /// The s saturation component. - /// The v value (brightness) component. - public Hsv(float h, float s, float v) - { - this.backingVector = Vector3.Clamp(new Vector3(h, s, v), Vector3.Zero, new Vector3(360, 1, 1)); - } - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public float H => this.backingVector.X; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public float S => this.backingVector.Y; - - /// - /// Gets the value (brightness) component. - /// A value ranging between 0 and 1. - /// - public float V => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Hsv(Color color) - { - float r = color.R / 255F; - float g = color.G / 255F; - float b = color.B / 255F; - - float max = Math.Max(r, Math.Max(g, b)); - float min = Math.Min(r, Math.Min(g, b)); - float chroma = max - min; - float h = 0; - float s = 0; - float v = max; - - if (Math.Abs(chroma) < Epsilon) - { - return new Hsv(0, s, v); - } - - if (Math.Abs(r - max) < Epsilon) - { - h = (g - b) / chroma; - } - else if (Math.Abs(g - max) < Epsilon) - { - h = 2 + ((b - r) / chroma); - } - else if (Math.Abs(b - max) < Epsilon) - { - h = 4 + ((r - g) / chroma); - } - - h *= 60; - if (h < 0.0) - { - h += 360; - } - - s = chroma / v; - - return new Hsv(h, s, v); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Hsv left, Hsv right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Hsv left, Hsv right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Hsv [ Empty ]"; - } - - return $"Hsv [ H={this.H:#0.##}, S={this.S:#0.##}, V={this.V:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Hsv) - { - return this.Equals((Hsv)obj); - } - - return false; - } - - /// - public bool Equals(Hsv other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(Hsv other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Hsv color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/IAlmostEquatable.cs b/src/ImageSharp46/Colors/Colorspaces/IAlmostEquatable.cs deleted file mode 100644 index 1163657ed..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/IAlmostEquatable.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// Defines a generalized method that a value type or class implements to create - /// a type-specific method for determining approximate equality of instances. - /// - /// The type of objects to compare. - /// The object specifying the type to specify precision with. - public interface IAlmostEquatable - where TPrecision : struct, IComparable - { - /// - /// Indicates whether the current object is equal to another object of the same type - /// when compared to the specified precision level. - /// - /// An object to compare with this object. - /// The object specifying the level of precision. - /// - /// true if the current object is equal to the other parameter; otherwise, false. - /// - bool AlmostEquals(TColor other, TPrecision precision); - } -} diff --git a/src/ImageSharp46/Colors/Colorspaces/YCbCr.cs b/src/ImageSharp46/Colors/Colorspaces/YCbCr.cs deleted file mode 100644 index c9a0872c5..000000000 --- a/src/ImageSharp46/Colors/Colorspaces/YCbCr.cs +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - - /// - /// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems. - /// - /// - public struct YCbCr : IEquatable - { - /// - /// Represents a that has Y, Cb, and Cr values set to zero. - /// - public static readonly YCbCr Empty = default(YCbCr); - - /// - /// Initializes a new instance of the struct. - /// - /// The y luminance component. - /// The cb chroma component. - /// The cr chroma component. - public YCbCr(byte y, byte cb, byte cr) - : this() - { - this.Y = y; - this.Cb = cb; - this.Cr = cr; - } - - /// - /// Gets the Y luminance component. - /// A value ranging between 0 and 255. - /// - public byte Y { get; } - - /// - /// Gets the Cb chroma component. - /// A value ranging between 0 and 255. - /// - public byte Cb { get; } - - /// - /// Gets the Cr chroma component. - /// A value ranging between 0 and 255. - /// - public byte Cr { get; } - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator YCbCr(Color color) - { - byte r = color.R; - byte g = color.G; - byte b = color.B; - - byte y = (byte)((0.299F * r) + (0.587F * g) + (0.114F * b)); - byte cb = (byte)(128 + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b))); - byte cr = (byte)(128 + ((0.5F * r) - (0.418688F * g) - (0.081312F * b))); - - return new YCbCr(y, cb, cr); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(YCbCr left, YCbCr right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(YCbCr left, YCbCr right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.Y.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Cb.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Cr.GetHashCode(); - return hashCode; - } - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "YCbCr [ Empty ]"; - } - - return $"YCbCr [ Y={this.Y}, Cb={this.Cb}, Cr={this.Cr} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is YCbCr) - { - return this.Equals((YCbCr)obj); - } - - return false; - } - - /// - public bool Equals(YCbCr other) - { - return this.Y == other.Y && this.Cb == other.Cb && this.Cr == other.Cr; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Colors/ComponentOrder.cs b/src/ImageSharp46/Colors/ComponentOrder.cs deleted file mode 100644 index 7372ab9bf..000000000 --- a/src/ImageSharp46/Colors/ComponentOrder.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerates the various component orders. - /// - public enum ComponentOrder - { - /// - /// Z-> Y-> X order. Equivalent to B-> G-> R in - /// - ZYX, - - /// - /// Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in - /// - ZYXW, - - /// - /// X-> Y-> Z order. Equivalent to R-> G-> B in - /// - XYZ, - - /// - /// X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in - /// - XYZW, - } -} diff --git a/src/ImageSharp46/Colors/PackedPixel/IPackedBytes.cs b/src/ImageSharp46/Colors/PackedPixel/IPackedBytes.cs deleted file mode 100644 index 5793ea1ba..000000000 --- a/src/ImageSharp46/Colors/PackedPixel/IPackedBytes.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// An interface that converts packed vector types to and from values, - /// allowing multiple encodings to be manipulated in a generic manner. - /// - public interface IPackedBytes - { - /// - /// Gets the packed representation from the gives bytes. - /// - /// The x-component. - /// The y-component. - /// The z-component. - /// The w-component. - void PackFromBytes(byte x, byte y, byte z, byte w); - - /// - /// Sets the packed representation into the gives bytes. - /// - /// The bytes to set the color in. - /// The starting index of the . - /// The order of the components. - void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder); - } -} diff --git a/src/ImageSharp46/Colors/PackedPixel/IPackedPixel.cs b/src/ImageSharp46/Colors/PackedPixel/IPackedPixel.cs deleted file mode 100644 index 54602380f..000000000 --- a/src/ImageSharp46/Colors/PackedPixel/IPackedPixel.cs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// An interface that represents a packed pixel type. - /// - /// The packed format. uint, long, float. - public interface IPackedPixel : IPackedVector, IPackedBytes - where TPacked : struct - { - } -} diff --git a/src/ImageSharp46/Colors/PackedPixel/IPackedVector.cs b/src/ImageSharp46/Colors/PackedPixel/IPackedVector.cs deleted file mode 100644 index cdf250a01..000000000 --- a/src/ImageSharp46/Colors/PackedPixel/IPackedVector.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Numerics; - - /// - /// An interface that converts packed vector types to and from values, - /// allowing multiple encodings to be manipulated in a generic manner. - /// - /// The packed format. uint, long, float. - public interface IPackedVector : IPackedVector - where TPacked : struct - { - /// - /// Gets or sets the packed representation of the value. - /// - TPacked PackedValue { get; set; } - } - - /// - /// An interface that converts packed vector types to and from values. - /// - public interface IPackedVector - { - /// - /// Sets the packed representation from a . - /// - /// The vector to create the packed representation from. - void PackFromVector4(Vector4 vector); - - /// - /// Expands the packed representation into a . - /// The vector components are typically expanded in least to greatest significance order. - /// - /// The . - Vector4 ToVector4(); - } -} diff --git a/src/ImageSharp46/Colors/RgbaComponent.cs b/src/ImageSharp46/Colors/RgbaComponent.cs deleted file mode 100644 index ed85fb86b..000000000 --- a/src/ImageSharp46/Colors/RgbaComponent.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerates the RGBA (red, green, blue, alpha) color components. - /// - public enum RgbaComponent - { - /// - /// The red component. - /// - R = 0, - - /// - /// The green component. - /// - G = 1, - - /// - /// The blue component. - /// - B = 2, - - /// - /// The alpha component. - /// - A = 3 - } -} diff --git a/src/ImageSharp46/Common/Exceptions/ImageFormatException.cs b/src/ImageSharp46/Common/Exceptions/ImageFormatException.cs deleted file mode 100644 index 70491ba22..000000000 --- a/src/ImageSharp46/Common/Exceptions/ImageFormatException.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// The exception that is thrown when the library tries to load - /// an image, which has an invalid format. - /// - public class ImageFormatException : Exception - { - /// - /// Initializes a new instance of the class. - /// - public ImageFormatException() - { - } - - /// - /// Initializes a new instance of the class with the name of the - /// parameter that causes this exception. - /// - /// The error message that explains the reason for this exception. - public ImageFormatException(string errorMessage) - : base(errorMessage) - { - } - - /// - /// Initializes a new instance of the class with a specified - /// error message and the exception that is the cause of this exception. - /// - /// The error message that explains the reason for this exception. - /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) - /// if no inner exception is specified. - public ImageFormatException(string errorMessage, Exception innerException) - : base(errorMessage, innerException) - { - } - } -} diff --git a/src/ImageSharp46/Common/Exceptions/ImageProcessingException.cs b/src/ImageSharp46/Common/Exceptions/ImageProcessingException.cs deleted file mode 100644 index a59be9ca8..000000000 --- a/src/ImageSharp46/Common/Exceptions/ImageProcessingException.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// The exception that is thrown when an error occurs when applying a process to an image. - /// - public class ImageProcessingException : Exception - { - /// - /// Initializes a new instance of the class. - /// - public ImageProcessingException() - { - } - - /// - /// Initializes a new instance of the class with the name of the - /// parameter that causes this exception. - /// - /// The error message that explains the reason for this exception. - public ImageProcessingException(string errorMessage) - : base(errorMessage) - { - } - - /// - /// Initializes a new instance of the class with a specified - /// error message and the exception that is the cause of this exception. - /// - /// The error message that explains the reason for this exception. - /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) - /// if no inner exception is specified. - public ImageProcessingException(string errorMessage, Exception innerException) - : base(errorMessage, innerException) - { - } - } -} diff --git a/src/ImageSharp46/Common/Extensions/ByteExtensions.cs b/src/ImageSharp46/Common/Extensions/ByteExtensions.cs deleted file mode 100644 index 89cfe6974..000000000 --- a/src/ImageSharp46/Common/Extensions/ByteExtensions.cs +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// Extension methods for the struct. - /// - internal static class ByteExtensions - { - /// - /// Converts a byte array to a new array where each value in the original array is represented - /// by a the specified number of bits. - /// - /// The bytes to convert from. Cannot be null. - /// The number of bits per value. - /// The resulting array. Is never null. - /// is null. - /// is less than or equals than zero. - public static byte[] ToArrayByBitsLength(this byte[] source, int bits) - { - Guard.NotNull(source, nameof(source)); - Guard.MustBeGreaterThan(bits, 0, "bits"); - - byte[] result; - - if (bits < 8) - { - result = new byte[source.Length * 8 / bits]; - int mask = 0xFF >> (8 - bits); - int resultOffset = 0; - - // ReSharper disable once ForCanBeConvertedToForeach - for (int i = 0; i < source.Length; i++) - { - byte b = source[i]; - for (int shift = 0; shift < 8; shift += bits) - { - int colorIndex = (b >> (8 - bits - shift)) & mask; - - result[resultOffset] = (byte)colorIndex; - - resultOffset++; - } - } - } - else - { - result = source; - } - - return result; - } - - /// - /// Optimized reversal algorithm. - /// - /// The byte array. - public static void ReverseBytes(this byte[] source) - { - ReverseBytes(source, 0, source.Length); - } - - /// - /// Optimized reversal algorithm. - /// - /// The byte array. - /// The index. - /// The length. - /// is null. - public static void ReverseBytes(this byte[] source, int index, int length) - { - Guard.NotNull(source, nameof(source)); - - int i = index; - int j = index + length - 1; - while (i < j) - { - byte temp = source[i]; - source[i] = source[j]; - source[j] = temp; - i++; - j--; - } - } - } -} diff --git a/src/ImageSharp46/Common/Extensions/ComparableExtensions.cs b/src/ImageSharp46/Common/Extensions/ComparableExtensions.cs deleted file mode 100644 index 6cc2eb588..000000000 --- a/src/ImageSharp46/Common/Extensions/ComparableExtensions.cs +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Runtime.CompilerServices; - -namespace ImageSharp -{ - using System; - - /// - /// Extension methods for classes that implement . - /// - internal static class ComparableExtensions - { - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - public static byte Clamp(this byte value, byte min, byte max) - { - // Order is important here as someone might set min to higher than max. - if (value > max) - { - return max; - } - - if (value < min) - { - return min; - } - - return value; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - public static uint Clamp(this uint value, uint min, uint max) - { - if (value > max) - { - return max; - } - - if (value < min) - { - return min; - } - - return value; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - public static int Clamp(this int value, int min, int max) - { - if (value > max) - { - return max; - } - - if (value < min) - { - return min; - } - - return value; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Clamp(this float value, float min, float max) - { - if (value > max) - { - return max; - } - - if (value < min) - { - return min; - } - - return value; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - public static double Clamp(this double value, double min, double max) - { - if (value > max) - { - return max; - } - - if (value < min) - { - return min; - } - - return value; - } - - /// - /// Converts an to a first restricting the value between the - /// minimum and maximum allowable ranges. - /// - /// The this method extends. - /// The - public static byte ToByte(this int value) - { - return (byte)value.Clamp(0, 255); - } - - /// - /// Converts an to a first restricting the value between the - /// minimum and maximum allowable ranges. - /// - /// The this method extends. - /// The - public static byte ToByte(this float value) - { - return (byte)value.Clamp(0, 255); - } - - /// - /// Converts an to a first restricting the value between the - /// minimum and maximum allowable ranges. - /// - /// The this method extends. - /// The - public static byte ToByte(this double value) - { - return (byte)value.Clamp(0, 255); - } - } -} diff --git a/src/ImageSharp46/Common/Extensions/EnumerableExtensions.cs b/src/ImageSharp46/Common/Extensions/EnumerableExtensions.cs deleted file mode 100644 index af8e50c7b..000000000 --- a/src/ImageSharp46/Common/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - - /// - /// Encapsulates a series of time saving extension methods to the interface. - /// - public static class EnumerableExtensions - { - /// - /// Generates a sequence of integral numbers within a specified range. - /// - /// - /// The start index, inclusive. - /// - /// - /// The end index, exclusive. - /// - /// - /// The incremental step. - /// - /// - /// The that contains a range of sequential integral numbers. - /// - public static IEnumerable SteppedRange(int fromInclusive, int toExclusive, int step) - { - // Borrowed from Enumerable.Range - long num = (fromInclusive + toExclusive) - 1L; - if ((toExclusive < 0) || (num > 0x7fffffffL)) - { - throw new ArgumentOutOfRangeException(nameof(toExclusive)); - } - - return RangeIterator(fromInclusive, i => i < toExclusive, step); - } - - /// - /// Generates a sequence of integral numbers within a specified range. - /// - /// - /// The start index, inclusive. - /// - /// - /// A method that has one parameter and returns a calculating the end index - /// - /// - /// The incremental step. - /// - /// - /// The that contains a range of sequential integral numbers. - /// - public static IEnumerable SteppedRange(int fromInclusive, Func toDelegate, int step) - { - return RangeIterator(fromInclusive, toDelegate, step); - } - - /// - /// Generates a sequence of integral numbers within a specified range. - /// - /// - /// The start index, inclusive. - /// - /// - /// A method that has one parameter and returns a calculating the end index - /// - /// - /// The incremental step. - /// - /// - /// The that contains a range of sequential integral numbers. - /// - private static IEnumerable RangeIterator(int fromInclusive, Func toDelegate, int step) - { - int i = fromInclusive; - while (toDelegate(i)) - { - yield return i; - i += step; - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Common/Extensions/StreamExtensions.cs b/src/ImageSharp46/Common/Extensions/StreamExtensions.cs deleted file mode 100644 index 87d5a6c32..000000000 --- a/src/ImageSharp46/Common/Extensions/StreamExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.IO; - - internal static class StreamExtensions - { - public static void Skip(this Stream stream, int count) - { - if (count < 1) - { - return; - } - - if (stream.CanSeek) - { - stream.Position += count; - } - else - { - byte[] foo = new byte[count]; - stream.Read(foo, 0, count); - } - } - } -} diff --git a/src/ImageSharp46/Common/Extensions/Vector4Extensions.cs b/src/ImageSharp46/Common/Extensions/Vector4Extensions.cs deleted file mode 100644 index 23fce0173..000000000 --- a/src/ImageSharp46/Common/Extensions/Vector4Extensions.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Numerics; - using System.Runtime.CompilerServices; - - /// - /// Extension methods for the struct. - /// - public static class Vector4Extensions - { - /// - /// Compresses a linear color signal to its sRGB equivalent. - /// - /// - /// - /// The whose signal to compress. - /// The . - public static Vector4 Compress(this Vector4 linear) - { - // TODO: Is there a faster way to do this? - return new Vector4(Compress(linear.X), Compress(linear.Y), Compress(linear.Z), linear.W); - } - - /// - /// Expands an sRGB color signal to its linear equivalent. - /// - /// - /// - /// The whose signal to expand. - /// The . - public static Vector4 Expand(this Vector4 gamma) - { - // TODO: Is there a faster way to do this? - return new Vector4(Expand(gamma.X), Expand(gamma.Y), Expand(gamma.Z), gamma.W); - } - - /// - /// Gets the compressed sRGB value from an linear signal. - /// - /// - /// - /// The signal value to compress. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float Compress(float signal) - { - if (signal <= 0.0031308F) - { - return signal * 12.92F; - } - - return (1.055F * (float)Math.Pow(signal, 0.41666666F)) - 0.055F; - } - - /// - /// Gets the expanded linear value from an sRGB signal. - /// - /// - /// - /// The signal value to expand. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float Expand(float signal) - { - if (signal <= 0.04045F) - { - return signal / 12.92F; - } - - return (float)Math.Pow((signal + 0.055F) / 1.055F, 2.4F); - } - } -} diff --git a/src/ImageSharp46/Common/Helpers/Guard.cs b/src/ImageSharp46/Common/Helpers/Guard.cs deleted file mode 100644 index ecb497d3e..000000000 --- a/src/ImageSharp46/Common/Helpers/Guard.cs +++ /dev/null @@ -1,205 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Diagnostics; - - /// - /// Provides methods to protect against invalid parameters. - /// - [DebuggerStepThrough] - internal static class Guard - { - /// - /// Verifies, that the method parameter with specified object value is not null - /// and throws an exception if it is found to be so. - /// - /// The target object, which cannot be null. - /// The name of the parameter that is to be checked. - /// The error message, if any to add to the exception. - /// is null - public static void NotNull(object target, string parameterName, string message = "") - { - if (target == null) - { - if (!string.IsNullOrWhiteSpace(message)) - { - throw new ArgumentNullException(parameterName, message); - } - - throw new ArgumentNullException(parameterName); - } - } - - /// - /// Verifies, that the string method parameter with specified object value and message - /// is not null, not empty and does not contain only blanks and throws an exception - /// if the object is null. - /// - /// The target string, which should be checked against being null or empty. - /// Name of the parameter. - /// is null. - /// is empty or contains only blanks. - public static void NotNullOrEmpty(string target, string parameterName) - { - if (target == null) - { - throw new ArgumentNullException(parameterName); - } - - if (string.IsNullOrWhiteSpace(target)) - { - throw new ArgumentException("Value cannot be null or empty and cannot contain only blanks.", parameterName); - } - } - - /// - /// Verifies that the specified value is less than a maximum value - /// and throws an exception if it is not. - /// - /// The target value, which should be validated. - /// The maximum value. - /// The name of the parameter that is to be checked. - /// The type of the value. - /// - /// is greater than the maximum value. - /// - public static void MustBeLessThan(TValue value, TValue max, string parameterName) - where TValue : IComparable - { - if (value.CompareTo(max) >= 0) - { - throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than {max}."); - } - } - - /// - /// Verifies that the specified value is less than or equal to a maximum value - /// and throws an exception if it is not. - /// - /// The target value, which should be validated. - /// The maximum value. - /// The name of the parameter that is to be checked. - /// The type of the value. - /// - /// is greater than the maximum value. - /// - public static void MustBeLessThanOrEqualTo(TValue value, TValue max, string parameterName) - where TValue : IComparable - { - if (value.CompareTo(max) > 0) - { - throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than or equal to {max}."); - } - } - - /// - /// Verifies that the specified value is greater than a minimum value - /// and throws an exception if it is not. - /// - /// The target value, which should be validated. - /// The minimum value. - /// The name of the parameter that is to be checked. - /// The type of the value. - /// - /// is less than the minimum value. - /// - public static void MustBeGreaterThan(TValue value, TValue min, string parameterName) - where TValue : IComparable - { - if (value.CompareTo(min) <= 0) - { - throw new ArgumentOutOfRangeException( - parameterName, - $"Value must be greater than {min}."); - } - } - - /// - /// Verifies that the specified value is greater than or equal to a minimum value - /// and throws an exception if it is not. - /// - /// The target value, which should be validated. - /// The minimum value. - /// The name of the parameter that is to be checked. - /// The type of the value. - /// - /// is less than the minimum value. - /// - public static void MustBeGreaterThanOrEqualTo(TValue value, TValue min, string parameterName) - where TValue : IComparable - { - if (value.CompareTo(min) < 0) - { - throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min}."); - } - } - - /// - /// Verifies that the specified value is greater than or equal to a minimum value and less than - /// or equal to a maximum value and throws an exception if it is not. - /// - /// The target value, which should be validated. - /// The minimum value. - /// The maximum value. - /// The name of the parameter that is to be checked. - /// The type of the value. - /// - /// is less than the minimum value of greater than the maximum value. - /// - public static void MustBeBetweenOrEqualTo(TValue value, TValue min, TValue max, string parameterName) - where TValue : IComparable - { - if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0) - { - throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min} and less than or equal to {max}."); - } - } - - /// - /// Verifies, that the method parameter with specified target value is true - /// and throws an exception if it is found to be so. - /// - /// - /// The target value, which cannot be false. - /// - /// - /// The name of the parameter that is to be checked. - /// - /// - /// The error message, if any to add to the exception. - /// - /// - /// is false - /// - public static void IsTrue(bool target, string parameterName, string message) - { - if (!target) - { - throw new ArgumentException(message, parameterName); - } - } - - /// - /// Verifies, that the method parameter with specified target value is false - /// and throws an exception if it is found to be so. - /// - /// The target value, which cannot be true. - /// The name of the parameter that is to be checked. - /// The error message, if any to add to the exception. - /// - /// is true - /// - public static void IsFalse(bool target, string parameterName, string message) - { - if (target) - { - throw new ArgumentException(message, parameterName); - } - } - } -} diff --git a/src/ImageSharp46/Common/Helpers/ImageMaths.cs b/src/ImageSharp46/Common/Helpers/ImageMaths.cs deleted file mode 100644 index 9b3c62382..000000000 --- a/src/ImageSharp46/Common/Helpers/ImageMaths.cs +++ /dev/null @@ -1,293 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Linq; - using System.Numerics; - - /// - /// Provides common mathematical methods. - /// - internal static class ImageMaths - { - /// - /// Returns how many bits are required to store the specified number of colors. - /// Performs a Log2() on the value. - /// - /// The number of colors. - /// - /// The - /// - public static int GetBitsNeededForColorDepth(int colors) - { - return (int)Math.Ceiling(Math.Log(colors, 2)); - } - - /// - /// Implementation of 1D Gaussian G(x) function - /// - /// The x provided to G(x). - /// The spread of the blur. - /// The Gaussian G(x) - public static float Gaussian(float x, float sigma) - { - const float Numerator = 1.0f; - float denominator = (float)(Math.Sqrt(2 * Math.PI) * sigma); - - float exponentNumerator = -x * x; - float exponentDenominator = (float)(2 * Math.Pow(sigma, 2)); - - float left = Numerator / denominator; - float right = (float)Math.Exp(exponentNumerator / exponentDenominator); - - return left * right; - } - - /// - /// Returns the result of a B-C filter against the given value. - /// - /// - /// The value to process. - /// The B-Spline curve variable. - /// The Cardinal curve variable. - /// - /// The . - /// - public static float GetBcValue(float x, float b, float c) - { - float temp; - - if (x < 0F) - { - x = -x; - } - - temp = x * x; - if (x < 1F) - { - x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b)); - return x / 6F; - } - - if (x < 2F) - { - x = ((-b - (6 * c)) * (x * temp)) + (((6 * b) + (30 * c)) * temp) + (((-12 * b) - (48 * c)) * x) + ((8 * b) + (24 * c)); - return x / 6F; - } - - return 0F; - } - - /// - /// Gets the result of a sine cardinal function for the given value. - /// - /// The value to calculate the result for. - /// - /// The . - /// - public static float SinC(float x) - { - const float Epsilon = .00001F; - - if (Math.Abs(x) > Epsilon) - { - x *= (float)Math.PI; - return Clean((float)Math.Sin(x) / x); - } - - return 1.0f; - } - - /// - /// Returns the given degrees converted to radians. - /// - /// The angle in degrees. - /// - /// The representing the degree as radians. - /// - public static float DegreesToRadians(float degrees) - { - return degrees * (float)(Math.PI / 180); - } - - /// - /// Gets the bounding from the given points. - /// - /// - /// The designating the top left position. - /// - /// - /// The designating the bottom right position. - /// - /// - /// The bounding . - /// - public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) - { - return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); - } - - /// - /// Gets the bounding from the given matrix. - /// - /// The source rectangle. - /// The transformation matrix. - /// - /// The . - /// - public static Rectangle GetBoundingRectangle(Rectangle rectangle, Matrix3x2 matrix) - { - Vector2 leftTop = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Top), matrix); - Vector2 rightTop = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Top), matrix); - Vector2 leftBottom = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Bottom), matrix); - Vector2 rightBottom = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Bottom), matrix); - - Vector2[] allCorners = { leftTop, rightTop, leftBottom, rightBottom }; - float extentX = allCorners.Select(v => v.X).Max() - allCorners.Select(v => v.X).Min(); - float extentY = allCorners.Select(v => v.Y).Max() - allCorners.Select(v => v.Y).Min(); - return new Rectangle(0, 0, (int)extentX, (int)extentY); - } - - /// - /// Finds the bounding rectangle based on the first instance of any color component other - /// than the given one. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to search within. - /// The color component value to remove. - /// The channel to test against. - /// - /// The . - /// - public static Rectangle GetFilteredBoundingRectangle(ImageBase bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) - where TColor : struct, IPackedPixel - where TPacked : struct - { - const float Epsilon = .00001f; - int width = bitmap.Width; - int height = bitmap.Height; - Point topLeft = default(Point); - Point bottomRight = default(Point); - - Func, int, int, float, bool> delegateFunc; - - // Determine which channel to check against - switch (channel) - { - case RgbaComponent.R: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Epsilon; - break; - - case RgbaComponent.G: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Epsilon; - break; - - case RgbaComponent.B: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Epsilon; - break; - - default: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Epsilon; - break; - } - - Func, int> getMinY = pixels => - { - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - if (delegateFunc(pixels, x, y, componentValue)) - { - return y; - } - } - } - - return 0; - }; - - Func, int> getMaxY = pixels => - { - for (int y = height - 1; y > -1; y--) - { - for (int x = 0; x < width; x++) - { - if (delegateFunc(pixels, x, y, componentValue)) - { - return y; - } - } - } - - return height; - }; - - Func, int> getMinX = pixels => - { - for (int x = 0; x < width; x++) - { - for (int y = 0; y < height; y++) - { - if (delegateFunc(pixels, x, y, componentValue)) - { - return x; - } - } - } - - return 0; - }; - - Func, int> getMaxX = pixels => - { - for (int x = width - 1; x > -1; x--) - { - for (int y = 0; y < height; y++) - { - if (delegateFunc(pixels, x, y, componentValue)) - { - return x; - } - } - } - - return height; - }; - - using (PixelAccessor bitmapPixels = bitmap.Lock()) - { - topLeft.Y = getMinY(bitmapPixels); - topLeft.X = getMinX(bitmapPixels); - bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height); - bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width); - } - - return GetBoundingRectangle(topLeft, bottomRight); - } - - /// - /// Ensures that any passed double is correctly rounded to zero - /// - /// The value to clean. - /// - /// The - /// . - private static float Clean(float x) - { - const float Epsilon = .00001F; - - if (Math.Abs(x) < Epsilon) - { - return 0F; - } - - return x; - } - } -} diff --git a/src/ImageSharp46/Filters/Alpha.cs b/src/ImageSharp46/Filters/Alpha.cs deleted file mode 100644 index a985165ad..000000000 --- a/src/ImageSharp46/Filters/Alpha.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the alpha component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new opacity of the image. Must be between 0 and 100. - /// The . - public static Image Alpha(this Image source, int percent) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Alpha(source, percent, source.Bounds); - } - - /// - /// Alters the alpha component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new opacity of the image. Must be between 0 and 100. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Alpha(this Image source, int percent, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new AlphaProcessor(percent)); - } - } -} diff --git a/src/ImageSharp46/Filters/BackgroundColor.cs b/src/ImageSharp46/Filters/BackgroundColor.cs deleted file mode 100644 index 47cbee4fb..000000000 --- a/src/ImageSharp46/Filters/BackgroundColor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Replaces the background color of image with the given one. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The color to set as the background. - /// The . - public static Image BackgroundColor(this Image source, TColor color) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(source.Bounds, new BackgroundColorProcessor(color)); - } - } -} diff --git a/src/ImageSharp46/Filters/BinaryThreshold.cs b/src/ImageSharp46/Filters/BinaryThreshold.cs deleted file mode 100644 index d97441fe2..000000000 --- a/src/ImageSharp46/Filters/BinaryThreshold.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies binerization to the image splitting the pixels at the given threshold. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The threshold to apply binerization of the image. Must be between 0 and 1. - /// The . - public static Image BinaryThreshold(this Image source, float threshold) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return BinaryThreshold(source, threshold, source.Bounds); - } - - /// - /// Applies binerization to the image splitting the pixels at the given threshold. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The threshold to apply binerization of the image. Must be between 0 and 1. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image BinaryThreshold(this Image source, float threshold, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new BinaryThresholdProcessor(threshold)); - } - } -} diff --git a/src/ImageSharp46/Filters/BlackWhite.cs b/src/ImageSharp46/Filters/BlackWhite.cs deleted file mode 100644 index 7e6c6601e..000000000 --- a/src/ImageSharp46/Filters/BlackWhite.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies black and white toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image BlackWhite(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return BlackWhite(source, source.Bounds); - } - - /// - /// Applies black and white toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image BlackWhite(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new BlackWhiteProcessor()); - } - } -} diff --git a/src/ImageSharp46/Filters/Blend.cs b/src/ImageSharp46/Filters/Blend.cs deleted file mode 100644 index 448fb7aa0..000000000 --- a/src/ImageSharp46/Filters/Blend.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Combines the given image together with the current one by blending their pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The opacity of the image image to blend. Must be between 0 and 100. - /// The . - public static Image Blend(this Image source, ImageBase image, int percent = 50) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Blend(source, image, percent, source.Bounds); - } - - /// - /// Combines the given image together with the current one by blending their pixels. - /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The pixel format. - /// The packed format. uint, long, float. - /// The opacity of the image image to blend. Must be between 0 and 100. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Blend(this Image source, ImageBase image, int percent, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new BlendProcessor(image, percent)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Brightness.cs b/src/ImageSharp46/Filters/Brightness.cs deleted file mode 100644 index 2e167c54f..000000000 --- a/src/ImageSharp46/Filters/Brightness.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the brightness component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new brightness of the image. Must be between -100 and 100. - /// The . - public static Image Brightness(this Image source, int amount) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Brightness(source, amount, source.Bounds); - } - - /// - /// Alters the brightness component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new brightness of the image. Must be between -100 and 100. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Brightness(this Image source, int amount, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new BrightnessProcessor(amount)); - } - } -} diff --git a/src/ImageSharp46/Filters/ColorBlindness.cs b/src/ImageSharp46/Filters/ColorBlindness.cs deleted file mode 100644 index e1a14e0f0..000000000 --- a/src/ImageSharp46/Filters/ColorBlindness.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies the given colorblindness simulator to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The type of color blindness simulator to apply. - /// The . - public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return ColorBlindness(source, colorBlindness, source.Bounds); - } - - /// - /// Applies the given colorblindness simulator to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The type of color blindness simulator to apply. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - IImageFilter processor; - - switch (colorBlindness) - { - case ImageSharp.ColorBlindness.Achromatomaly: - processor = new AchromatomalyProcessor(); - break; - - case ImageSharp.ColorBlindness.Achromatopsia: - processor = new AchromatopsiaProcessor(); - break; - - case ImageSharp.ColorBlindness.Deuteranomaly: - processor = new DeuteranomalyProcessor(); - break; - - case ImageSharp.ColorBlindness.Deuteranopia: - processor = new DeuteranopiaProcessor(); - break; - - case ImageSharp.ColorBlindness.Protanomaly: - processor = new ProtanomalyProcessor(); - break; - - case ImageSharp.ColorBlindness.Protanopia: - processor = new ProtanopiaProcessor(); - break; - - case ImageSharp.ColorBlindness.Tritanomaly: - processor = new TritanomalyProcessor(); - break; - - default: - processor = new TritanopiaProcessor(); - break; - } - - return source.Process(rectangle, processor); - } - } -} diff --git a/src/ImageSharp46/Filters/Contrast.cs b/src/ImageSharp46/Filters/Contrast.cs deleted file mode 100644 index 6f9c45cc6..000000000 --- a/src/ImageSharp46/Filters/Contrast.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the contrast component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new contrast of the image. Must be between -100 and 100. - /// The . - public static Image Contrast(this Image source, int amount) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Contrast(source, amount, source.Bounds); - } - - /// - /// Alters the contrast component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new contrast of the image. Must be between -100 and 100. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Contrast(this Image source, int amount, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new ContrastProcessor(amount)); - } - } -} diff --git a/src/ImageSharp46/Filters/Glow.cs b/src/ImageSharp46/Filters/Glow.cs deleted file mode 100644 index 1b829850d..000000000 --- a/src/ImageSharp46/Filters/Glow.cs +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a radial glow effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Glow(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Glow(source, default(TColor), source.Bounds.Width * .5F, source.Bounds); - } - - /// - /// Applies a radial glow effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The color to set as the glow. - /// The . - public static Image Glow(this Image source, TColor color) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Glow(source, color, source.Bounds.Width * .5F, source.Bounds); - } - - /// - /// Applies a radial glow effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The the radius. - /// The . - public static Image Glow(this Image source, float radius) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Glow(source, default(TColor), radius, source.Bounds); - } - - /// - /// Applies a radial glow effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Glow(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Glow(source, default(TColor), 0, rectangle); - } - - /// - /// Applies a radial glow effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The color to set as the glow. - /// The the radius. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Glow(this Image source, TColor color, float radius, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - GlowProcessor processor = new GlowProcessor { Radius = radius, }; - - if (!color.Equals(default(TColor))) - { - processor.GlowColor = color; - } - - return source.Process(rectangle, processor); - } - } -} diff --git a/src/ImageSharp46/Filters/Grayscale.cs b/src/ImageSharp46/Filters/Grayscale.cs deleted file mode 100644 index ce827e54c..000000000 --- a/src/ImageSharp46/Filters/Grayscale.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies Grayscale toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The formula to apply to perform the operation. - /// The . - public static Image Grayscale(this Image source, GrayscaleMode mode = GrayscaleMode.Bt709) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Grayscale(source, source.Bounds, mode); - } - - /// - /// Applies Grayscale toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The formula to apply to perform the operation. - /// The . - public static Image Grayscale(this Image source, Rectangle rectangle, GrayscaleMode mode = GrayscaleMode.Bt709) - where TColor : struct, IPackedPixel - where TPacked : struct - { - IImageFilter processor = mode == GrayscaleMode.Bt709 - ? (IImageFilter)new GrayscaleBt709Processor() - : new GrayscaleBt601Processor(); - - return source.Process(rectangle, processor); - } - } -} diff --git a/src/ImageSharp46/Filters/Hue.cs b/src/ImageSharp46/Filters/Hue.cs deleted file mode 100644 index c146667a0..000000000 --- a/src/ImageSharp46/Filters/Hue.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the hue component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The angle in degrees to adjust the image. - /// The . - public static Image Hue(this Image source, float degrees) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Hue(source, degrees, source.Bounds); - } - - /// - /// Alters the hue component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The angle in degrees to adjust the image. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Hue(this Image source, float degrees, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new HueProcessor(degrees)); - } - } -} diff --git a/src/ImageSharp46/Filters/Invert.cs b/src/ImageSharp46/Filters/Invert.cs deleted file mode 100644 index a948c511d..000000000 --- a/src/ImageSharp46/Filters/Invert.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Inverts the colors of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Invert(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Invert(source, source.Bounds); - } - - /// - /// Inverts the colors of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Invert(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new InvertProcessor()); - } - } -} diff --git a/src/ImageSharp46/Filters/Kodachrome.cs b/src/ImageSharp46/Filters/Kodachrome.cs deleted file mode 100644 index f47bfa5c3..000000000 --- a/src/ImageSharp46/Filters/Kodachrome.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the colors of the image recreating an old Kodachrome camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Kodachrome(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Kodachrome(source, source.Bounds); - } - - /// - /// Alters the colors of the image recreating an old Kodachrome camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Kodachrome(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new KodachromeProcessor()); - } - } -} diff --git a/src/ImageSharp46/Filters/Lomograph.cs b/src/ImageSharp46/Filters/Lomograph.cs deleted file mode 100644 index 84fccd374..000000000 --- a/src/ImageSharp46/Filters/Lomograph.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the colors of the image recreating an old Lomograph camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Lomograph(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Lomograph(source, source.Bounds); - } - - /// - /// Alters the colors of the image recreating an old Lomograph camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Lomograph(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new LomographProcessor()); - } - } -} diff --git a/src/ImageSharp46/Filters/Options/ColorBlindness.cs b/src/ImageSharp46/Filters/Options/ColorBlindness.cs deleted file mode 100644 index 1e0bc596b..000000000 --- a/src/ImageSharp46/Filters/Options/ColorBlindness.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerates the various types of defined color blindness filters. - /// - public enum ColorBlindness - { - /// - /// Partial color desensitivity. - /// - Achromatomaly, - - /// - /// Complete color desensitivity (Monochrome) - /// - Achromatopsia, - - /// - /// Green weak - /// - Deuteranomaly, - - /// - /// Green blind - /// - Deuteranopia, - - /// - /// Red weak - /// - Protanomaly, - - /// - /// Red blind - /// - Protanopia, - - /// - /// Blue weak - /// - Tritanomaly, - - /// - /// Blue blind - /// - Tritanopia - } -} diff --git a/src/ImageSharp46/Filters/Options/EdgeDetection.cs b/src/ImageSharp46/Filters/Options/EdgeDetection.cs deleted file mode 100644 index 67fad0de4..000000000 --- a/src/ImageSharp46/Filters/Options/EdgeDetection.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerates the various types of defined edge detection filters. - /// - public enum EdgeDetection - { - /// - /// The Kayyali operator filter. - /// - Kayyali, - - /// - /// The Kirsch operator filter. - /// - Kirsch, - - /// - /// The Lapacian3X3 operator filter. - /// - Lapacian3X3, - - /// - /// The Lapacian5X5 operator filter. - /// - Lapacian5X5, - - /// - /// The LaplacianOfGaussian operator filter. - /// - LaplacianOfGaussian, - - /// - /// The Prewitt operator filter. - /// - Prewitt, - - /// - /// The RobertsCross operator filter. - /// - RobertsCross, - - /// - /// The Robinson operator filter. - /// - Robinson, - - /// - /// The Scharr operator filter. - /// - Scharr, - - /// - /// The Sobel operator filter. - /// - Sobel - } -} diff --git a/src/ImageSharp46/Filters/Options/GrayscaleMode.cs b/src/ImageSharp46/Filters/Options/GrayscaleMode.cs deleted file mode 100644 index 6ecd5bb36..000000000 --- a/src/ImageSharp46/Filters/Options/GrayscaleMode.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerates the various types of defined Grayscale filters. - /// - public enum GrayscaleMode - { - /// - /// ITU-R Recommendation BT.709 - /// - Bt709, - - /// - /// ITU-R Recommendation BT.601 - /// - Bt601 - } -} diff --git a/src/ImageSharp46/Filters/Polaroid.cs b/src/ImageSharp46/Filters/Polaroid.cs deleted file mode 100644 index f77c95a4b..000000000 --- a/src/ImageSharp46/Filters/Polaroid.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the colors of the image recreating an old Polaroid camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Polaroid(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Polaroid(source, source.Bounds); - } - - /// - /// Alters the colors of the image recreating an old Polaroid camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Polaroid(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new PolaroidProcessor()); - } - } -} diff --git a/src/ImageSharp46/Filters/Processors/AlphaProcessor.cs b/src/ImageSharp46/Filters/Processors/AlphaProcessor.cs deleted file mode 100644 index 08c05acdd..000000000 --- a/src/ImageSharp46/Filters/Processors/AlphaProcessor.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the alpha component of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class AlphaProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The percentage to adjust the opacity of the image. Must be between 0 and 100. - /// - /// is less than 0 or is greater than 100. - /// - public AlphaProcessor(int percent) - { - Guard.MustBeBetweenOrEqualTo(percent, 0, 100, nameof(percent)); - this.Value = percent; - } - - /// - /// Gets the alpha value. - /// - public int Value { get; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - float alpha = this.Value / 100F; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - Vector4 alphaVector = new Vector4(1, 1, 1, alpha); - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - TColor packed = default(TColor); - packed.PackFromVector4(sourcePixels[offsetX, offsetY].ToVector4() * alphaVector); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} diff --git a/src/ImageSharp46/Filters/Processors/BackgroundColorProcessor.cs b/src/ImageSharp46/Filters/Processors/BackgroundColorProcessor.cs deleted file mode 100644 index 37dd580fa..000000000 --- a/src/ImageSharp46/Filters/Processors/BackgroundColorProcessor.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Sets the background color of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BackgroundColorProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - - /// - /// Initializes a new instance of the class. - /// - /// The to set the background color to. - public BackgroundColorProcessor(TColor color) - { - this.Value = color; - } - - /// - /// Gets the background color value. - /// - public TColor Value { get; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - Vector4 backgroundColor = this.Value.ToVector4(); - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); - float a = color.W; - - if (a < 1 && a > 0) - { - color = Vector4.Lerp(color, backgroundColor, .5F); - } - - if (Math.Abs(a) < Epsilon) - { - color = backgroundColor; - } - - TColor packed = default(TColor); - packed.PackFromVector4(color); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp46/Filters/Processors/Binarization/BinaryThresholdProcessor.cs deleted file mode 100644 index 09c6a96f3..000000000 --- a/src/ImageSharp46/Filters/Processors/Binarization/BinaryThresholdProcessor.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// An to perform binary threshold filtering against an - /// . The image will be converted to grayscale before thresholding occurs. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BinaryThresholdProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The threshold to split the image. Must be between 0 and 1. - /// - /// is less than 0 or is greater than 1. - /// - public BinaryThresholdProcessor(float threshold) - { - // TODO: Check limit. - Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); - this.Value = threshold; - - TColor upper = default(TColor); - upper.PackFromVector4(Color.White.ToVector4()); - this.UpperColor = upper; - - TColor lower = default(TColor); - lower.PackFromVector4(Color.Black.ToVector4()); - this.LowerColor = lower; - } - - /// - /// Gets the threshold value. - /// - public float Value { get; } - - /// - /// Gets or sets the color to use for pixels that are above the threshold. - /// - public TColor UpperColor { get; set; } - - /// - /// Gets or sets the color to use for pixels that fall below the threshold. - /// - public TColor LowerColor { get; set; } - - /// - protected override void OnApply(ImageBase source, Rectangle sourceRectangle) - { - new GrayscaleBt709Processor().Apply(source, sourceRectangle); - } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - float threshold = this.Value; - TColor upper = this.UpperColor; - TColor lower = this.LowerColor; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - TColor color = sourcePixels[offsetX, offsetY]; - - // Any channel will do since it's Grayscale. - sourcePixels[offsetX, offsetY] = color.ToVector4().X >= threshold ? upper : lower; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/BlendProcessor.cs b/src/ImageSharp46/Filters/Processors/BlendProcessor.cs deleted file mode 100644 index 4f326361f..000000000 --- a/src/ImageSharp46/Filters/Processors/BlendProcessor.cs +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Combines two images together by blending the pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BlendProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The image to blend. - /// - private readonly ImageBase blend; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The image to blend with the currently processing image. - /// Disposal of this image is the responsibility of the developer. - /// - /// The opacity of the image to blend. Between 0 and 100. - public BlendProcessor(ImageBase image, int alpha = 100) - { - Guard.MustBeBetweenOrEqualTo(alpha, 0, 100, nameof(alpha)); - this.blend = image; - this.Value = alpha; - } - - /// - /// Gets the alpha percentage value. - /// - public int Value { get; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Rectangle bounds = this.blend.Bounds; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - float alpha = this.Value / 100F; - - using (PixelAccessor toBlendPixels = this.blend.Lock()) - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); - - if (bounds.Contains(offsetX, offsetY)) - { - Vector4 blendedColor = toBlendPixels[offsetX, offsetY].ToVector4(); - - if (blendedColor.W > 0) - { - // Lerping colors is dependent on the alpha of the blended color - color = Vector4.Lerp(color, blendedColor, alpha > 0 ? alpha : blendedColor.W); - } - } - - TColor packed = default(TColor); - packed.PackFromVector4(color); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/BrightnessProcessor.cs b/src/ImageSharp46/Filters/Processors/BrightnessProcessor.cs deleted file mode 100644 index b74759b6b..000000000 --- a/src/ImageSharp46/Filters/Processors/BrightnessProcessor.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the brightness of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BrightnessProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The new brightness of the image. Must be between -100 and 100. - /// - /// is less than -100 or is greater than 100. - /// - public BrightnessProcessor(int brightness) - { - Guard.MustBeBetweenOrEqualTo(brightness, -100, 100, nameof(brightness)); - this.Value = brightness; - } - - /// - /// Gets the brightness value. - /// - public int Value { get; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - float brightness = this.Value / 100F; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - - // TODO: Check this with other formats. - Vector4 vector = sourcePixels[offsetX, offsetY].ToVector4().Expand(); - Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness); - vector = new Vector4(transformed, vector.W); - - TColor packed = default(TColor); - packed.PackFromVector4(vector.Compress()); - - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs deleted file mode 100644 index cbb351aaf..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to their black and white equivalent. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BlackWhiteProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 1.5f, - M12 = 1.5f, - M13 = 1.5f, - M21 = 1.5f, - M22 = 1.5f, - M23 = 1.5f, - M31 = 1.5f, - M32 = 1.5f, - M33 = 1.5f, - M41 = -1f, - M42 = -1f, - M43 = -1f, - }; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs deleted file mode 100644 index 012954c2f..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class AchromatomalyProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = .618f, - M12 = .163f, - M13 = .163f, - M21 = .320f, - M22 = .775f, - M23 = .320f, - M31 = .062f, - M32 = .062f, - M33 = .516f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs deleted file mode 100644 index 6ce50ba43..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class AchromatopsiaProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = .299f, - M12 = .299f, - M13 = .299f, - M21 = .587f, - M22 = .587f, - M23 = .587f, - M31 = .114f, - M32 = .114f, - M33 = .114f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs deleted file mode 100644 index e1fbac60a..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class DeuteranomalyProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.8f, - M12 = 0.258f, - M21 = 0.2f, - M22 = 0.742f, - M23 = 0.142f, - M33 = 0.858f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs deleted file mode 100644 index 35e76b235..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class DeuteranopiaProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.625f, - M12 = 0.7f, - M21 = 0.375f, - M22 = 0.3f, - M23 = 0.3f, - M33 = 0.7f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs deleted file mode 100644 index 38199b956..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class ProtanomalyProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.817f, - M12 = 0.333f, - M21 = 0.183f, - M22 = 0.667f, - M23 = 0.125f, - M33 = 0.875f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs deleted file mode 100644 index 19936a849..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class ProtanopiaProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.567f, - M12 = 0.558f, - M21 = 0.433f, - M22 = 0.442f, - M23 = 0.242f, - M33 = 0.758f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/README.md b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/README.md deleted file mode 100644 index 209f3b67b..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Color blindness matrices adapted from and tested against: - -http://web.archive.org/web/20090413045433/http://nofunc.org/Color_Matrix_Library -http://www.color-blindness.com/coblis-color-blindness-simulator/ \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs deleted file mode 100644 index 84d22c78a..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class TritanomalyProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.967f, - M21 = 0.33f, - M22 = 0.733f, - M23 = 0.183f, - M32 = 0.267f, - M33 = 0.817f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs deleted file mode 100644 index 82d7415b7..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class TritanopiaProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.95f, - M21 = 0.05f, - M22 = 0.433f, - M23 = 0.475f, - M32 = 0.567f, - M33 = 0.525f - }; - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs deleted file mode 100644 index be6f277e0..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// The color matrix filter. Inherit from this class to perform operation involving color matrices. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class ColorMatrixFilter : ImageFilter, IColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public abstract Matrix4x4 Matrix { get; } - - /// - public override bool Compand { get; set; } = true; - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - Matrix4x4 matrix = this.Matrix; - bool compand = this.Compand; - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - sourcePixels[offsetX, offsetY] = this.ApplyMatrix(sourcePixels[offsetX, offsetY], matrix, compand); - } - }); - } - } - - /// - /// Applies the color matrix against the given color. - /// - /// The source color. - /// The matrix. - /// Whether to compand the color during processing. - /// - /// The . - /// - private TColor ApplyMatrix(TColor color, Matrix4x4 matrix, bool compand) - { - Vector4 vector = color.ToVector4(); - - if (compand) - { - vector = vector.Expand(); - } - - Vector3 transformed = Vector3.Transform(new Vector3(vector.X, vector.Y, vector.Z), matrix); - vector = new Vector4(transformed, vector.W); - TColor packed = default(TColor); - packed.PackFromVector4(compand ? vector.Compress() : vector); - return packed; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt601Processor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt601Processor.cs deleted file mode 100644 index d6c1762e8..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt601Processor.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to Grayscale applying the formula as specified by - /// ITU-R Recommendation BT.601 . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class GrayscaleBt601Processor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = .299f, - M12 = .299f, - M13 = .299f, - M21 = .587f, - M22 = .587f, - M23 = .587f, - M31 = .114f, - M32 = .114f, - M33 = .114f - }; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt709Processor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt709Processor.cs deleted file mode 100644 index 6fbde6418..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/GrayscaleBt709Processor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to Grayscale applying the formula as specified by - /// ITU-R Recommendation BT.709 . - /// - public class GrayscaleBt709Processor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = .2126f, - M12 = .2126f, - M13 = .2126f, - M21 = .7152f, - M22 = .7152f, - M23 = .7152f, - M31 = .0722f, - M32 = .0722f, - M33 = .0722f - }; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/HueProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/HueProcessor.cs deleted file mode 100644 index a829331c9..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/HueProcessor.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - - /// - /// An to change the hue of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class HueProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The new brightness of the image. Must be between -100 and 100. - public HueProcessor(float angle) - { - // Wrap the angle round at 360. - angle = angle % 360; - - // Make sure it's not negative. - while (angle < 0) - { - angle += 360; - } - - this.Angle = angle; - - float radians = ImageMaths.DegreesToRadians(angle); - double cosradians = Math.Cos(radians); - double sinradians = Math.Sin(radians); - - float lumR = .213f; - float lumG = .715f; - float lumB = .072f; - - float oneMinusLumR = 1 - lumR; - float oneMinusLumG = 1 - lumG; - float oneMinusLumB = 1 - lumB; - - // The matrix is set up to preserve the luminance of the image. - // See http://graficaobscura.com/matrix/index.html - // Number are taken from https://msdn.microsoft.com/en-us/library/jj192162(v=vs.85).aspx - Matrix4x4 matrix4X4 = new Matrix4x4() - { - M11 = (float)(lumR + (cosradians * oneMinusLumR) - (sinradians * lumR)), - M12 = (float)(lumR - (cosradians * lumR) - (sinradians * 0.143)), - M13 = (float)(lumR - (cosradians * lumR) - (sinradians * oneMinusLumR)), - M21 = (float)(lumG - (cosradians * lumG) - (sinradians * lumG)), - M22 = (float)(lumG + (cosradians * oneMinusLumG) + (sinradians * 0.140)), - M23 = (float)(lumG - (cosradians * lumG) + (sinradians * lumG)), - M31 = (float)(lumB - (cosradians * lumB) + (sinradians * oneMinusLumB)), - M32 = (float)(lumB - (cosradians * lumB) - (sinradians * 0.283)), - M33 = (float)(lumB + (cosradians * oneMinusLumB) + (sinradians * lumB)) - }; - - this.Matrix = matrix4X4; - } - - /// - /// Gets the rotation value. - /// - public float Angle { get; } - - /// - public override Matrix4x4 Matrix { get; } - - /// - public override bool Compand => false; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs deleted file mode 100644 index ede66fd71..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Encapsulates properties and methods for creating processors that utilize a matrix to - /// alter the image pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IColorMatrixFilter : IImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Gets the used to alter the image. - /// - Matrix4x4 Matrix { get; } - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/KodachromeProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/KodachromeProcessor.cs deleted file mode 100644 index a4f58cc41..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/KodachromeProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Kodachrome camera effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class KodachromeProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 0.6997023f, - M22 = 0.4609577f, - M33 = 0.397218f, - M41 = 0.005f, - M42 = -0.005f, - M43 = 0.005f - }; - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/LomographProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/LomographProcessor.cs deleted file mode 100644 index 628c13087..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/LomographProcessor.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Lomograph effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class LomographProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 1.5f, - M22 = 1.45f, - M33 = 1.11f, - M41 = -.1f, - M42 = .0f, - M43 = -.08f - }; - - /// - protected override void AfterApply(ImageBase source, Rectangle sourceRectangle) - { - TColor packed = default(TColor); - packed.PackFromVector4(new Color(0, 10, 0).ToVector4()); // Very dark (mostly black) lime green. - new VignetteProcessor { VignetteColor = packed }.Apply(source, sourceRectangle); - } - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/PolaroidProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/PolaroidProcessor.cs deleted file mode 100644 index 72fc0a98d..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/PolaroidProcessor.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Polaroid effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class PolaroidProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = 1.538f, - M12 = -0.062f, - M13 = -0.262f, - M21 = -0.022f, - M22 = 1.578f, - M23 = -0.022f, - M31 = .216f, - M32 = -.16f, - M33 = 1.5831f, - M41 = 0.02f, - M42 = -0.05f, - M43 = -0.05f - }; - - /// - protected override void AfterApply(ImageBase source, Rectangle sourceRectangle) - { - TColor packedV = default(TColor); - packedV.PackFromVector4(new Color(102, 34, 0).ToVector4()); // Very dark orange [Brown tone] - new VignetteProcessor { VignetteColor = packedV }.Apply(source, sourceRectangle); - - TColor packedG = default(TColor); - packedG.PackFromVector4(new Color(255, 153, 102, 178).ToVector4()); // Light orange - new GlowProcessor { GlowColor = packedG, Radius = source.Width / 4F }.Apply(source, sourceRectangle); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/SaturationProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/SaturationProcessor.cs deleted file mode 100644 index 60f7c7815..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/SaturationProcessor.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// An to change the saturation of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class SaturationProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The new saturation of the image. Must be between -100 and 100. - /// - /// is less than -100 or is greater than 100. - /// - public SaturationProcessor(int saturation) - { - Guard.MustBeBetweenOrEqualTo(saturation, -100, 100, nameof(saturation)); - float saturationFactor = saturation / 100f; - - // Stop at -1 to prevent inversion. - saturationFactor++; - - // The matrix is set up to "shear" the colour space using the following set of values. - // Note that each colour component has an effective luminance which contributes to the - // overall brightness of the pixel. - // See http://graficaobscura.com/matrix/index.html - float saturationComplement = 1.0f - saturationFactor; - float saturationComplementR = 0.3086f * saturationComplement; - float saturationComplementG = 0.6094f * saturationComplement; - float saturationComplementB = 0.0820f * saturationComplement; - - Matrix4x4 matrix4X4 = new Matrix4x4() - { - M11 = saturationComplementR + saturationFactor, - M12 = saturationComplementR, - M13 = saturationComplementR, - M21 = saturationComplementG, - M22 = saturationComplementG + saturationFactor, - M23 = saturationComplementG, - M31 = saturationComplementB, - M32 = saturationComplementB, - M33 = saturationComplementB + saturationFactor, - }; - - this.Matrix = matrix4X4; - } - - /// - public override Matrix4x4 Matrix { get; } - } -} diff --git a/src/ImageSharp46/Filters/Processors/ColorMatrix/SepiaProcessor.cs b/src/ImageSharp46/Filters/Processors/ColorMatrix/SepiaProcessor.cs deleted file mode 100644 index 80be3bf4c..000000000 --- a/src/ImageSharp46/Filters/Processors/ColorMatrix/SepiaProcessor.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to their sepia equivalent. - /// The formula used matches the svg specification. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class SepiaProcessor : ColorMatrixFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override Matrix4x4 Matrix => new Matrix4x4() - { - M11 = .393f, - M12 = .349f, - M13 = .272f, - M21 = .769f, - M22 = .686f, - M23 = .534f, - M31 = .189f, - M32 = .168f, - M33 = .131f - }; - - /// - public override bool Compand => false; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/ContrastProcessor.cs b/src/ImageSharp46/Filters/Processors/ContrastProcessor.cs deleted file mode 100644 index fbcaaa1cd..000000000 --- a/src/ImageSharp46/Filters/Processors/ContrastProcessor.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the contrast of an . - /// - /// The pixel format. - /// The packed format. long, float. - public class ContrastProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The new contrast of the image. Must be between -100 and 100. - /// - /// is less than -100 or is greater than 100. - /// - public ContrastProcessor(int contrast) - { - Guard.MustBeBetweenOrEqualTo(contrast, -100, 100, nameof(contrast)); - this.Value = contrast; - } - - /// - /// Gets the contrast value. - /// - public int Value { get; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - float contrast = (100F + this.Value) / 100F; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Vector4 contrastVector = new Vector4(contrast, contrast, contrast, 1); - Vector4 shiftVector = new Vector4(.5F, .5F, .5F, 1); - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - - Vector4 vector = sourcePixels[offsetX, offsetY].ToVector4().Expand(); - vector -= shiftVector; - vector *= contrastVector; - vector += shiftVector; - TColor packed = default(TColor); - packed.PackFromVector4(vector.Compress()); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/GlowProcessor.cs b/src/ImageSharp46/Filters/Processors/GlowProcessor.cs deleted file mode 100644 index d671d1d6f..000000000 --- a/src/ImageSharp46/Filters/Processors/GlowProcessor.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An that applies a radial glow effect an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class GlowProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - public GlowProcessor() - { - TColor color = default(TColor); - color.PackFromVector4(Color.Black.ToVector4()); - this.GlowColor = color; - } - - /// - /// Gets or sets the glow color to apply. - /// - public TColor GlowColor { get; set; } - - /// - /// Gets or sets the the radius. - /// - public float Radius { get; set; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - TColor glowColor = this.GlowColor; - Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); - float maxDistance = this.Radius > 0 ? Math.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; - Ellipse ellipse = new Ellipse(new Point(centre), maxDistance, maxDistance); - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - if (ellipse.Contains(offsetX, offsetY)) - { - // TODO: Premultiply? - float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY)); - Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4(); - TColor packed = default(TColor); - packed.PackFromVector4(Vector4.Lerp(glowColor.ToVector4(), sourceColor, distance / maxDistance)); - sourcePixels[offsetX, offsetY] = packed; - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/IImageFilter.cs b/src/ImageSharp46/Filters/Processors/IImageFilter.cs deleted file mode 100644 index fc0a7625b..000000000 --- a/src/ImageSharp46/Filters/Processors/IImageFilter.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Encapsulates methods to alter the pixels of an image. The processor operates on the original source pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IImageFilter : IImageProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Applies the process to the specified portion of the specified . - /// - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// The method keeps the source image unchanged and returns the - /// the result of image processing filter as new image. - /// - /// - /// is null. - /// - /// - /// doesnt fit the dimension of the image. - /// - void Apply(ImageBase source, Rectangle sourceRectangle); - } -} diff --git a/src/ImageSharp46/Filters/Processors/ImageFilter.cs b/src/ImageSharp46/Filters/Processors/ImageFilter.cs deleted file mode 100644 index 34bfdb1fb..000000000 --- a/src/ImageSharp46/Filters/Processors/ImageFilter.cs +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - - /// - /// Encapsulates methods to alter the pixels of an image. The processor operates on the original source pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class ImageFilter : ImageProcessor, IImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public void Apply(ImageBase source, Rectangle sourceRectangle) - { - try - { - this.OnApply(source, sourceRectangle); - - this.Apply(source, sourceRectangle, sourceRectangle.Y, sourceRectangle.Bottom); - - this.AfterApply(source, sourceRectangle); - } - catch (Exception ex) - { - throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex); - } - } - - /// - /// Applies the process to the specified portion of the specified at the specified location - /// and with the specified size. - /// - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The index of the row within the source image to start processing. - /// The index of the row within the source image to end processing. - protected abstract void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY); - - /// - /// This method is called before the process is applied to prepare the processor. - /// - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - protected virtual void OnApply(ImageBase source, Rectangle sourceRectangle) - { - } - - /// - /// This method is called after the process is applied to prepare the processor. - /// - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - protected virtual void AfterApply(ImageBase source, Rectangle sourceRectangle) - { - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/InvertProcessor.cs b/src/ImageSharp46/Filters/Processors/InvertProcessor.cs deleted file mode 100644 index d010eaf36..000000000 --- a/src/ImageSharp46/Filters/Processors/InvertProcessor.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to invert the colors of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class InvertProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Vector3 inverseVector = Vector3.One; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); - Vector3 vector = inverseVector - new Vector3(color.X, color.Y, color.Z); - - TColor packed = default(TColor); - packed.PackFromVector4(new Vector4(vector, color.W)); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Processors/VignetteProcessor.cs b/src/ImageSharp46/Filters/Processors/VignetteProcessor.cs deleted file mode 100644 index b60e49647..000000000 --- a/src/ImageSharp46/Filters/Processors/VignetteProcessor.cs +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An that applies a radial vignette effect to an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class VignetteProcessor : ImageFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - public VignetteProcessor() - { - TColor color = default(TColor); - color.PackFromVector4(Color.Black.ToVector4()); - this.VignetteColor = color; - } - - /// - /// Gets or sets the vignette color to apply. - /// - public TColor VignetteColor { get; set; } - - /// - /// Gets or sets the the x-radius. - /// - public float RadiusX { get; set; } - - /// - /// Gets or sets the the y-radius. - /// - public float RadiusY { get; set; } - - /// - protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - TColor vignetteColor = this.VignetteColor; - Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); - float rX = this.RadiusX > 0 ? Math.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; - float rY = this.RadiusY > 0 ? Math.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F; - float maxDistance = (float)Math.Sqrt((rX * rX) + (rY * rY)); - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY)); - Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4(); - TColor packed = default(TColor); - packed.PackFromVector4(Vector4.Lerp(vignetteColor.ToVector4(), sourceColor, 1 - (.9F * (distance / maxDistance)))); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Saturation.cs b/src/ImageSharp46/Filters/Saturation.cs deleted file mode 100644 index 6fb0a463c..000000000 --- a/src/ImageSharp46/Filters/Saturation.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the saturation component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new saturation of the image. Must be between -100 and 100. - /// The . - public static Image Saturation(this Image source, int amount) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Saturation(source, amount, source.Bounds); - } - - /// - /// Alters the saturation component of the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The new saturation of the image. Must be between -100 and 100. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Saturation(this Image source, int amount, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new SaturationProcessor(amount)); - } - } -} diff --git a/src/ImageSharp46/Filters/Sepia.cs b/src/ImageSharp46/Filters/Sepia.cs deleted file mode 100644 index 6bd070cc8..000000000 --- a/src/ImageSharp46/Filters/Sepia.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies sepia toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Sepia(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Sepia(source, source.Bounds); - } - - /// - /// Applies sepia toning to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Sepia(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new SepiaProcessor()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Filters/Vignette.cs b/src/ImageSharp46/Filters/Vignette.cs deleted file mode 100644 index b8f10b27a..000000000 --- a/src/ImageSharp46/Filters/Vignette.cs +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a radial vignette effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image Vignette(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Vignette(source, default(TColor), source.Bounds.Width * .5F, source.Bounds.Height * .5F, source.Bounds); - } - - /// - /// Applies a radial vignette effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The color to set as the vignette. - /// The . - public static Image Vignette(this Image source, TColor color) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Vignette(source, color, source.Bounds.Width * .5F, source.Bounds.Height * .5F, source.Bounds); - } - - /// - /// Applies a radial vignette effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The the x-radius. - /// The the y-radius. - /// The . - public static Image Vignette(this Image source, float radiusX, float radiusY) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Vignette(source, default(TColor), radiusX, radiusY, source.Bounds); - } - - /// - /// Applies a radial vignette effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Vignette(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Vignette(source, default(TColor), 0, 0, rectangle); - } - - /// - /// Applies a radial vignette effect to an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The color to set as the vignette. - /// The the x-radius. - /// The the y-radius. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Vignette(this Image source, TColor color, float radiusX, float radiusY, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - VignetteProcessor processor = new VignetteProcessor { RadiusX = radiusX, RadiusY = radiusY }; - - if (!color.Equals(default(TColor))) - { - processor.VignetteColor = color; - } - - return source.Process(rectangle, processor); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp46/Formats/Bmp/BmpBitsPerPixel.cs deleted file mode 100644 index 330326acf..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpBitsPerPixel.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Enumerates the available bits per pixel for bitmap. - /// - public enum BmpBitsPerPixel - { - /// - /// 24 bits per pixel. Each pixel consists of 3 bytes. - /// - Pixel24 = 3, - - /// - /// 32 bits per pixel. Each pixel consists of 4 bytes. - /// - Pixel32 = 4, - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpCompression.cs b/src/ImageSharp46/Formats/Bmp/BmpCompression.cs deleted file mode 100644 index a9246d449..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpCompression.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Defines how the compression type of the image data - /// in the bitmap file. - /// - internal enum BmpCompression - { - /// - /// Each image row has a multiple of four elements. If the - /// row has less elements, zeros will be added at the right side. - /// The format depends on the number of bits, stored in the info header. - /// If the number of bits are one, four or eight each pixel data is - /// a index to the palette. If the number of bits are sixteen, - /// twenty-four or thirty-two each pixel contains a color. - /// - RGB = 0, - - /// - /// Two bytes are one data record. If the first byte is not zero, the - /// next two half bytes will be repeated as much as the value of the first byte. - /// If the first byte is zero, the record has different meanings, depending - /// on the second byte. If the second byte is zero, it is the end of the row, - /// if it is one, it is the end of the image. - /// Not supported at the moment. - /// - RLE8 = 1, - - /// - /// Two bytes are one data record. If the first byte is not zero, the - /// next byte will be repeated as much as the value of the first byte. - /// If the first byte is zero, the record has different meanings, depending - /// on the second byte. If the second byte is zero, it is the end of the row, - /// if it is one, it is the end of the image. - /// Not supported at the moment. - /// - RLE4 = 2, - - /// - /// Each image row has a multiple of four elements. If the - /// row has less elements, zeros will be added at the right side. - /// Not supported at the moment. - /// - BitFields = 3, - - /// - /// The bitmap contains a JPG image. - /// Not supported at the moment. - /// - JPEG = 4, - - /// - /// The bitmap contains a PNG image. - /// Not supported at the moment. - /// - PNG = 5 - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp46/Formats/Bmp/BmpDecoder.cs deleted file mode 100644 index b99a96462..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpDecoder.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Image decoder for generating an image out of a Windows bitmap stream. - /// - /// - /// Does not support the following formats at the moment: - /// - /// JPG - /// PNG - /// RLE4 - /// RLE8 - /// BitFields - /// - /// Formats will be supported in a later releases. We advise always - /// to use only 24 Bit Windows bitmaps. - /// - public class BmpDecoder : IImageDecoder - { - /// - /// Gets the size of the header for this image type. - /// - /// The size of the header. - public int HeaderSize => 2; - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file extension. - /// - /// True if the decoder supports the file extension; otherwise, false. - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, "extension"); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - - return extension.Equals("BMP", StringComparison.OrdinalIgnoreCase) - || extension.Equals("DIP", StringComparison.OrdinalIgnoreCase); - } - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file header. - /// - /// True if the decoder supports the file header; otherwise, false. - /// - public bool IsSupportedFileFormat(byte[] header) - { - bool isBmp = false; - if (header.Length >= 2) - { - isBmp = header[0] == 0x42 && // B - header[1] == 0x4D; // M - } - - return isBmp; - } - - /// - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, "image"); - Guard.NotNull(stream, "stream"); - - new BmpDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp46/Formats/Bmp/BmpDecoderCore.cs deleted file mode 100644 index 7c3e842aa..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpDecoderCore.cs +++ /dev/null @@ -1,404 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Performs the bmp decoding operation. - /// - internal sealed class BmpDecoderCore - { - /// - /// The mask for the red part of the color for 16 bit rgb bitmaps. - /// - private const int Rgb16RMask = 0x00007C00; - - /// - /// The mask for the green part of the color for 16 bit rgb bitmaps. - /// - private const int Rgb16GMask = 0x000003E0; - - /// - /// The mask for the blue part of the color for 16 bit rgb bitmaps. - /// - private const int Rgb16BMask = 0x0000001F; - - /// - /// The stream to decode from. - /// - private Stream currentStream; - - /// - /// The file header containing general information. - /// TODO: Why is this not used? We advance the stream but do not use the values parsed. - /// - private BmpFileHeader fileHeader; - - /// - /// The info header containing detailed information about the bitmap. - /// - private BmpInfoHeader infoHeader; - - /// - /// Decodes the image from the specified this._stream and sets - /// the data to image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image, where the data should be set to. - /// Cannot be null (Nothing in Visual Basic). - /// The stream, where the image should be - /// decoded from. Cannot be null (Nothing in Visual Basic). - /// - /// is null. - /// - or - - /// is null. - /// - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - this.currentStream = stream; - - try - { - this.ReadFileHeader(); - this.ReadInfoHeader(); - - // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517 - // If the height is negative, then this is a Windows bitmap whose origin - // is the upper-left corner and not the lower-left.The inverted flag - // indicates a lower-left origin.Our code will be outputting an - // upper-left origin pixel array. - bool inverted = false; - if (this.infoHeader.Height < 0) - { - inverted = true; - this.infoHeader.Height = -this.infoHeader.Height; - } - - int colorMapSize = -1; - - if (this.infoHeader.ClrUsed == 0) - { - if (this.infoHeader.BitsPerPixel == 1 || - this.infoHeader.BitsPerPixel == 4 || - this.infoHeader.BitsPerPixel == 8) - { - colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4; - } - } - else - { - colorMapSize = this.infoHeader.ClrUsed * 4; - } - - byte[] palette = null; - - if (colorMapSize > 0) - { - // 256 * 4 - if (colorMapSize > 1024) - { - throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'"); - } - - palette = new byte[colorMapSize]; - - this.currentStream.Read(palette, 0, colorMapSize); - } - - if (this.infoHeader.Width > image.MaxWidth || this.infoHeader.Height > image.MaxHeight) - { - throw new ArgumentOutOfRangeException( - $"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is " - + $"bigger then the max allowed size '{image.MaxWidth}x{image.MaxHeight}'"); - } - - image.InitPixels(this.infoHeader.Width, this.infoHeader.Height); - - using (PixelAccessor pixels = image.Lock()) - { - switch (this.infoHeader.Compression) - { - case BmpCompression.RGB: - if (this.infoHeader.HeaderSize != 40) - { - throw new ImageFormatException($"Header Size value '{this.infoHeader.HeaderSize}' is not valid."); - } - - if (this.infoHeader.BitsPerPixel == 32) - { - this.ReadRgb32(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel == 24) - { - this.ReadRgb24(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel == 16) - { - this.ReadRgb16(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel <= 8) - { - this.ReadRgbPalette(pixels, palette, this.infoHeader.Width, this.infoHeader.Height, this.infoHeader.BitsPerPixel, inverted); - } - - break; - default: - throw new NotSupportedException("Does not support this kind of bitmap files."); - } - } - } - catch (IndexOutOfRangeException e) - { - throw new ImageFormatException("Bitmap does not have a valid format.", e); - } - } - - /// - /// Returns the y- value based on the given height. - /// - /// The y- value representing the current row. - /// The height of the bitmap. - /// Whether the bitmap is inverted. - /// The representing the inverted value. - private static int Invert(int y, int height, bool inverted) - { - int row; - - if (!inverted) - { - row = height - y - 1; - } - else - { - row = y; - } - - return row; - } - - /// - /// Calculates the amount of bytes to pad a row. - /// - /// The image width. - /// The pixel component count. - /// - /// The . - /// - private static int CalculatePadding(int width, int componentCount) - { - int padding = (width * componentCount) % 4; - - if (padding != 0) - { - padding = 4 - padding; - } - - return padding; - } - - /// - /// Reads the color palette from the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to assign the palette to. - /// The containing the colors. - /// The width of the bitmap. - /// The height of the bitmap. - /// The number of bits per pixel. - /// Whether the bitmap is inverted. - private void ReadRgbPalette(PixelAccessor pixels, byte[] colors, int width, int height, int bits, bool inverted) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Pixels per byte (bits per pixel) - int ppb = 8 / bits; - - int arrayWidth = (width + ppb - 1) / ppb; - - // Bit mask - int mask = 0xFF >> (8 - bits); - - // Rows are aligned on 4 byte boundaries - int padding = arrayWidth % 4; - if (padding != 0) - { - padding = 4 - padding; - } - - byte[] row = new byte[arrayWidth + padding]; - TColor color = default(TColor); - - for (int y = 0; y < height; y++) - { - int newY = Invert(y, height, inverted); - - this.currentStream.Read(row, 0, row.Length); - - int offset = 0; - for (int x = 0; x < arrayWidth; x++) - { - int colOffset = x * ppb; - - for (int shift = 0; shift < ppb && (x + shift) < width; shift++) - { - int colorIndex = ((row[offset] >> (8 - bits - (shift * bits))) & mask) * 4; - int newX = colOffset + shift; - - // Stored in b-> g-> r order. - color.PackFromBytes(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex], 255); - pixels[newX, newY] = color; - } - - offset++; - } - } - } - - /// - /// Reads the 16 bit color palette from the stream - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - /// Whether the bitmap is inverted. - private void ReadRgb16(PixelAccessor pixels, int width, int height, bool inverted) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // We divide here as we will store the colors in our floating point format. - const int ScaleR = 8; // 256/32 - const int ScaleG = 4; // 256/64 - const int ComponentCount = 2; - - TColor color = default(TColor); - using (PixelRow row = new PixelRow(width, ComponentOrder.XYZ)) - { - for (int y = 0; y < height; y++) - { - row.Read(this.currentStream); - - int newY = Invert(y, height, inverted); - - int offset = 0; - for (int x = 0; x < width; x++) - { - short temp = BitConverter.ToInt16(row.Bytes, offset); - - byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR); - byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG); - byte b = (byte)((temp & Rgb16BMask) * ScaleR); - - color.PackFromBytes(r, g, b, 255); - pixels[x, newY] = color; - offset += ComponentCount; - } - } - } - } - - /// - /// Reads the 24 bit color palette from the stream - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - /// Whether the bitmap is inverted. - private void ReadRgb24(PixelAccessor pixels, int width, int height, bool inverted) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int padding = CalculatePadding(width, 3); - using (PixelRow row = new PixelRow(width, ComponentOrder.ZYX, padding)) - { - for (int y = 0; y < height; y++) - { - row.Read(this.currentStream); - - int newY = Invert(y, height, inverted); - pixels.CopyFrom(row, newY); - } - } - } - - /// - /// Reads the 32 bit color palette from the stream - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - /// Whether the bitmap is inverted. - private void ReadRgb32(PixelAccessor pixels, int width, int height, bool inverted) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int padding = CalculatePadding(width, 4); - using (PixelRow row = new PixelRow(width, ComponentOrder.ZYXW, padding)) - { - for (int y = 0; y < height; y++) - { - row.Read(this.currentStream); - - int newY = Invert(y, height, inverted); - pixels.CopyFrom(row, newY); - } - } - } - - /// - /// Reads the from the stream. - /// - private void ReadInfoHeader() - { - byte[] data = new byte[BmpInfoHeader.Size]; - - this.currentStream.Read(data, 0, BmpInfoHeader.Size); - - this.infoHeader = new BmpInfoHeader - { - HeaderSize = BitConverter.ToInt32(data, 0), - Width = BitConverter.ToInt32(data, 4), - Height = BitConverter.ToInt32(data, 8), - Planes = BitConverter.ToInt16(data, 12), - BitsPerPixel = BitConverter.ToInt16(data, 14), - ImageSize = BitConverter.ToInt32(data, 20), - XPelsPerMeter = BitConverter.ToInt32(data, 24), - YPelsPerMeter = BitConverter.ToInt32(data, 28), - ClrUsed = BitConverter.ToInt32(data, 32), - ClrImportant = BitConverter.ToInt32(data, 36), - Compression = (BmpCompression)BitConverter.ToInt32(data, 16) - }; - } - - /// - /// Reads the from the stream. - /// - private void ReadFileHeader() - { - byte[] data = new byte[BmpFileHeader.Size]; - - this.currentStream.Read(data, 0, BmpFileHeader.Size); - - this.fileHeader = new BmpFileHeader - { - Type = BitConverter.ToInt16(data, 0), - FileSize = BitConverter.ToInt32(data, 2), - Reserved = BitConverter.ToInt32(data, 6), - Offset = BitConverter.ToInt32(data, 10) - }; - } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp46/Formats/Bmp/BmpEncoder.cs deleted file mode 100644 index 7205840b7..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpEncoder.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Image encoder for writing an image to a stream as a Windows bitmap. - /// - /// The encoder can currently only write 24-bit rgb images to streams. - public class BmpEncoder : IImageEncoder - { - /// - /// Gets or sets the quality of output for images. - /// - /// Bitmap is a lossless format so this is not used in this encoder. - public int Quality { get; set; } - - /// - public string MimeType => "image/bmp"; - - /// - public string Extension => "bmp"; - - /// - /// Gets or sets the number of bits per pixel. - /// - public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24; - - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, nameof(extension)); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - - return extension.Equals(this.Extension, StringComparison.OrdinalIgnoreCase) - || extension.Equals("dip", StringComparison.OrdinalIgnoreCase); - } - - /// - public void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - BmpEncoderCore encoder = new BmpEncoderCore(); - encoder.Encode(image, stream, this.BitsPerPixel); - } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp46/Formats/Bmp/BmpEncoderCore.cs deleted file mode 100644 index 7c3d18b93..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpEncoderCore.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System.IO; - - using IO; - - /// - /// Image encoder for writing an image to a stream as a Windows bitmap. - /// - internal sealed class BmpEncoderCore - { - /// - /// The number of bits per pixel. - /// - private BmpBitsPerPixel bmpBitsPerPixel; - - /// - /// The amount to pad each row by. - /// - private int padding; - - /// - /// Encodes the image to the specified stream from the . - /// - /// The pixel format. - /// The packed format. long, float. - /// The to encode from. - /// The to encode the image data to. - /// The - public void Encode(ImageBase image, Stream stream, BmpBitsPerPixel bitsPerPixel) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - this.bmpBitsPerPixel = bitsPerPixel; - - // Cast to int will get the bytes per pixel - short bpp = (short)(8 * (int)bitsPerPixel); - int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); - this.padding = bytesPerLine - (image.Width * (int)bitsPerPixel); - - // Do not use IDisposable pattern here as we want to preserve the stream. - EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Little, stream); - - BmpInfoHeader infoHeader = new BmpInfoHeader - { - HeaderSize = BmpInfoHeader.Size, - Height = image.Height, - Width = image.Width, - BitsPerPixel = bpp, - Planes = 1, - ImageSize = image.Height * bytesPerLine, - ClrUsed = 0, - ClrImportant = 0 - }; - - BmpFileHeader fileHeader = new BmpFileHeader - { - Type = 19778, // BM - Offset = 54, - FileSize = 54 + infoHeader.ImageSize - }; - - WriteHeader(writer, fileHeader); - this.WriteInfo(writer, infoHeader); - this.WriteImage(writer, image); - - writer.Flush(); - } - - /// - /// Writes the bitmap header data to the binary stream. - /// - /// - /// The containing the stream to write to. - /// - /// - /// The containing the header data. - /// - private static void WriteHeader(EndianBinaryWriter writer, BmpFileHeader fileHeader) - { - writer.Write(fileHeader.Type); - writer.Write(fileHeader.FileSize); - writer.Write(fileHeader.Reserved); - writer.Write(fileHeader.Offset); - } - - /// - /// Writes the bitmap information to the binary stream. - /// - /// - /// The containing the stream to write to. - /// - /// - /// The containing the detailed information about the image. - /// - private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader) - { - writer.Write(infoHeader.HeaderSize); - writer.Write(infoHeader.Width); - writer.Write(infoHeader.Height); - writer.Write(infoHeader.Planes); - writer.Write(infoHeader.BitsPerPixel); - writer.Write((int)infoHeader.Compression); - writer.Write(infoHeader.ImageSize); - writer.Write(infoHeader.XPelsPerMeter); - writer.Write(infoHeader.YPelsPerMeter); - writer.Write(infoHeader.ClrUsed); - writer.Write(infoHeader.ClrImportant); - } - - /// - /// Writes the pixel data to the binary stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing the stream to write to. - /// - /// The containing pixel data. - /// - private void WriteImage(EndianBinaryWriter writer, ImageBase image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - switch (this.bmpBitsPerPixel) - { - case BmpBitsPerPixel.Pixel32: - this.Write32Bit(writer, pixels); - break; - - case BmpBitsPerPixel.Pixel24: - this.Write24Bit(writer, pixels); - break; - } - } - } - - /// - /// Writes the 32bit color palette to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing the stream to write to. - /// The containing pixel data. - private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelRow row = new PixelRow(pixels.Width, ComponentOrder.ZYXW, this.padding)) - { - for (int y = pixels.Height - 1; y >= 0; y--) - { - pixels.CopyTo(row, y); - writer.Write(row.Bytes); - } - } - } - - /// - /// Writes the 24bit color palette to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing the stream to write to. - /// The containing pixel data. - private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelRow row = new PixelRow(pixels.Width, ComponentOrder.ZYX, this.padding)) - { - for (int y = pixels.Height - 1; y >= 0; y--) - { - pixels.CopyTo(row, y); - writer.Write(row.Bytes); - } - } - } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpFileHeader.cs b/src/ImageSharp46/Formats/Bmp/BmpFileHeader.cs deleted file mode 100644 index 4be602f4b..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpFileHeader.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Stores general information about the Bitmap file. - /// - /// - /// - /// The first two bytes of the Bitmap file format - /// (thus the Bitmap header) are stored in big-endian order. - /// All of the other integer values are stored in little-endian format - /// (i.e. least-significant byte first). - /// - internal class BmpFileHeader - { - /// - /// Defines of the data structure in the bitmap file. - /// - public const int Size = 14; - - /// - /// Gets or sets the Bitmap identifier. - /// The field used to identify the bitmap file: 0x42 0x4D - /// (Hex code points for B and M) - /// - public short Type { get; set; } - - /// - /// Gets or sets the size of the bitmap file in bytes. - /// - public int FileSize { get; set; } - - /// - /// Gets or sets any reserved data; actual value depends on the application - /// that creates the image. - /// - public int Reserved { get; set; } - - /// - /// Gets or sets the offset, i.e. starting address, of the byte where - /// the bitmap data can be found. - /// - public int Offset { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpFormat.cs b/src/ImageSharp46/Formats/Bmp/BmpFormat.cs deleted file mode 100644 index b01f3ab32..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpFormat.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Encapsulates the means to encode and decode bitmap images. - /// - public class BmpFormat : IImageFormat - { - /// - public IImageDecoder Decoder => new BmpDecoder(); - - /// - public IImageEncoder Encoder => new BmpEncoder(); - } -} diff --git a/src/ImageSharp46/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp46/Formats/Bmp/BmpInfoHeader.cs deleted file mode 100644 index e652cb504..000000000 --- a/src/ImageSharp46/Formats/Bmp/BmpInfoHeader.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp.Formats -{ - /// - /// This block of bytes tells the application detailed information - /// about the image, which will be used to display the image on - /// the screen. - /// - /// - internal class BmpInfoHeader - { - /// - /// Defines of the data structure in the bitmap file. - /// - public const int Size = 40; - - /// - /// Gets or sets the size of this header (40 bytes) - /// - public int HeaderSize { get; set; } - - /// - /// Gets or sets the bitmap width in pixels (signed integer). - /// - public int Width { get; set; } - - /// - /// Gets or sets the bitmap height in pixels (signed integer). - /// - public int Height { get; set; } - - /// - /// Gets or sets the number of color planes being used. Must be set to 1. - /// - public short Planes { get; set; } - - /// - /// Gets or sets the number of bits per pixel, which is the color depth of the image. - /// Typical values are 1, 4, 8, 16, 24 and 32. - /// - public short BitsPerPixel { get; set; } - - /// - /// Gets or sets the compression method being used. - /// See the next table for a list of possible values. - /// - public BmpCompression Compression { get; set; } - - /// - /// Gets or sets the image size. This is the size of the raw bitmap data (see below), - /// and should not be confused with the file size. - /// - public int ImageSize { get; set; } - - /// - /// Gets or sets the horizontal resolution of the image. - /// (pixel per meter, signed integer) - /// - public int XPelsPerMeter { get; set; } - - /// - /// Gets or sets the vertical resolution of the image. - /// (pixel per meter, signed integer) - /// - public int YPelsPerMeter { get; set; } - - /// - /// Gets or sets the number of colors in the color palette, - /// or 0 to default to 2^n. - /// - public int ClrUsed { get; set; } - - /// - /// Gets or sets the number of important colors used, - /// or 0 when every color is important{ get; set; } generally ignored. - /// - public int ClrImportant { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Bmp/README.md b/src/ImageSharp46/Formats/Bmp/README.md deleted file mode 100644 index d07283843..000000000 --- a/src/ImageSharp46/Formats/Bmp/README.md +++ /dev/null @@ -1,8 +0,0 @@ -Encoder/Decoder adapted from: - -https://github.com/yufeih/Nine.Imaging/ -https://imagetools.codeplex.com/ - -TODO: - -- Add support for all bitmap formats. diff --git a/src/ImageSharp46/Formats/Gif/DisposalMethod.cs b/src/ImageSharp46/Formats/Gif/DisposalMethod.cs deleted file mode 100644 index 80b5f3c6e..000000000 --- a/src/ImageSharp46/Formats/Gif/DisposalMethod.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Provides enumeration for instructing the decoder what to do with the last image - /// in an animation sequence. - /// section 23 - /// - public enum DisposalMethod - { - /// - /// No disposal specified. The decoder is not required to take any action. - /// - Unspecified = 0, - - /// - /// Do not dispose. The graphic is to be left in place. - /// - NotDispose = 1, - - /// - /// Restore to background color. The area used by the graphic must be restored to - /// the background color. - /// - RestoreToBackground = 2, - - /// - /// Restore to previous. The decoder is required to restore the area overwritten by the - /// graphic with what was there prior to rendering the graphic. - /// - RestoreToPrevious = 3 - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifConstants.cs b/src/ImageSharp46/Formats/Gif/GifConstants.cs deleted file mode 100644 index 5334bcba3..000000000 --- a/src/ImageSharp46/Formats/Gif/GifConstants.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Constants that define specific points within a gif. - /// - internal sealed class GifConstants - { - /// - /// The file type. - /// - public const string FileType = "GIF"; - - /// - /// The file version. - /// - public const string FileVersion = "89a"; - - /// - /// The extension block introducer !. - /// - public const byte ExtensionIntroducer = 0x21; - - /// - /// The graphic control label. - /// - public const byte GraphicControlLabel = 0xF9; - - /// - /// The application extension label. - /// - public const byte ApplicationExtensionLabel = 0xFF; - - /// - /// The application identification. - /// - public const string ApplicationIdentification = "NETSCAPE2.0"; - - /// - /// The application block size. - /// - public const byte ApplicationBlockSize = 0x0b; - - /// - /// The comment label. - /// - public const byte CommentLabel = 0xFE; - - /// - /// The maximum comment length. - /// - public const int MaxCommentLength = 1024 * 8; - - /// - /// The image descriptor label ,. - /// - public const byte ImageDescriptorLabel = 0x2C; - - /// - /// The plain text label. - /// - public const byte PlainTextLabel = 0x01; - - /// - /// The image label introducer ,. - /// - public const byte ImageLabel = 0x2C; - - /// - /// The terminator. - /// - public const byte Terminator = 0; - - /// - /// The end introducer trailer ;. - /// - public const byte EndIntroducer = 0x3B; - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifDecoder.cs b/src/ImageSharp46/Formats/Gif/GifDecoder.cs deleted file mode 100644 index 4afc1cfdb..000000000 --- a/src/ImageSharp46/Formats/Gif/GifDecoder.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Decoder for generating an image out of a gif encoded stream. - /// - public class GifDecoder : IImageDecoder - { - /// - /// Gets the size of the header for this image type. - /// - /// The size of the header. - public int HeaderSize => 6; - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file extension. - /// - /// True if the decoder supports the file extension; otherwise, false. - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, nameof(extension)); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - return extension.Equals("GIF", StringComparison.OrdinalIgnoreCase); - } - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file header. - /// - /// True if the decoder supports the file header; otherwise, false. - /// - public bool IsSupportedFileFormat(byte[] header) - { - return header.Length >= 6 && - header[0] == 0x47 && // G - header[1] == 0x49 && // I - header[2] == 0x46 && // F - header[3] == 0x38 && // 8 - (header[4] == 0x39 || header[4] == 0x37) && // 9 or 7 - header[5] == 0x61; // a - } - - /// - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - new GifDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp46/Formats/Gif/GifDecoderCore.cs deleted file mode 100644 index 44bb5553b..000000000 --- a/src/ImageSharp46/Formats/Gif/GifDecoderCore.cs +++ /dev/null @@ -1,425 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Performs the gif decoding operation. - /// - /// The pixel format. - /// The packed format. uint, long, float. - internal class GifDecoderCore - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The image to decode the information to. - /// - private Image decodedImage; - - /// - /// The currently loaded stream. - /// - private Stream currentStream; - - /// - /// The global color table. - /// - private byte[] globalColorTable; - - /// - /// The current frame. - /// - private TColor[] currentFrame; - - /// - /// The logical screen descriptor. - /// - private GifLogicalScreenDescriptor logicalScreenDescriptor; - - /// - /// The graphics control extension. - /// - private GifGraphicsControlExtension graphicsControlExtension; - - /// - /// Decodes the stream to the image. - /// - /// The image to decode to. - /// The stream containing image data. - public void Decode(Image image, Stream stream) - { - this.decodedImage = image; - - this.currentStream = stream; - - // Skip the identifier - this.currentStream.Skip(6); - this.ReadLogicalScreenDescriptor(); - - if (this.logicalScreenDescriptor.GlobalColorTableFlag) - { - this.globalColorTable = new byte[this.logicalScreenDescriptor.GlobalColorTableSize * 3]; - - // Read the global color table from the stream - stream.Read(this.globalColorTable, 0, this.globalColorTable.Length); - } - - // Loop though the respective gif parts and read the data. - int nextFlag = stream.ReadByte(); - while (nextFlag != GifConstants.Terminator) - { - if (nextFlag == GifConstants.ImageLabel) - { - this.ReadFrame(); - } - else if (nextFlag == GifConstants.ExtensionIntroducer) - { - int label = stream.ReadByte(); - switch (label) - { - case GifConstants.GraphicControlLabel: - this.ReadGraphicalControlExtension(); - break; - case GifConstants.CommentLabel: - this.ReadComments(); - break; - case GifConstants.ApplicationExtensionLabel: - this.Skip(12); // No need to read. - break; - case GifConstants.PlainTextLabel: - this.Skip(13); // Not supported by any known decoder. - break; - } - } - else if (nextFlag == GifConstants.EndIntroducer) - { - break; - } - - nextFlag = stream.ReadByte(); - } - } - - /// - /// Reads the graphic control extension. - /// - private void ReadGraphicalControlExtension() - { - byte[] buffer = new byte[6]; - - this.currentStream.Read(buffer, 0, buffer.Length); - - byte packed = buffer[1]; - - this.graphicsControlExtension = new GifGraphicsControlExtension - { - DelayTime = BitConverter.ToInt16(buffer, 2), - TransparencyIndex = buffer[4], - TransparencyFlag = (packed & 0x01) == 1, - DisposalMethod = (DisposalMethod)((packed & 0x1C) >> 2) - }; - } - - /// - /// Reads the image descriptor - /// - /// - private GifImageDescriptor ReadImageDescriptor() - { - byte[] buffer = new byte[9]; - - this.currentStream.Read(buffer, 0, buffer.Length); - - byte packed = buffer[8]; - - GifImageDescriptor imageDescriptor = new GifImageDescriptor - { - Left = BitConverter.ToInt16(buffer, 0), - Top = BitConverter.ToInt16(buffer, 2), - Width = BitConverter.ToInt16(buffer, 4), - Height = BitConverter.ToInt16(buffer, 6), - LocalColorTableFlag = ((packed & 0x80) >> 7) == 1, - LocalColorTableSize = 2 << (packed & 0x07), - InterlaceFlag = ((packed & 0x40) >> 6) == 1 - }; - - return imageDescriptor; - } - - /// - /// Reads the logical screen descriptor. - /// - private void ReadLogicalScreenDescriptor() - { - byte[] buffer = new byte[7]; - - this.currentStream.Read(buffer, 0, buffer.Length); - - byte packed = buffer[4]; - - this.logicalScreenDescriptor = new GifLogicalScreenDescriptor - { - Width = BitConverter.ToInt16(buffer, 0), - Height = BitConverter.ToInt16(buffer, 2), - BackgroundColorIndex = buffer[5], - PixelAspectRatio = buffer[6], - GlobalColorTableFlag = ((packed & 0x80) >> 7) == 1, - GlobalColorTableSize = 2 << (packed & 0x07) - }; - - if (this.logicalScreenDescriptor.GlobalColorTableSize > 255 * 4) - { - throw new ImageFormatException( - $"Invalid gif colormap size '{this.logicalScreenDescriptor.GlobalColorTableSize}'"); - } - - if (this.logicalScreenDescriptor.Width > this.decodedImage.MaxWidth || this.logicalScreenDescriptor.Height > this.decodedImage.MaxHeight) - { - throw new ArgumentOutOfRangeException( - $"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{this.decodedImage.MaxWidth}x{this.decodedImage.MaxHeight}'"); - } - } - - /// - /// Skips the designated number of bytes in the stream. - /// - /// The number of bytes to skip. - private void Skip(int length) - { - this.currentStream.Skip(length); - - int flag; - - while ((flag = this.currentStream.ReadByte()) != 0) - { - this.currentStream.Skip(flag); - } - } - - /// - /// Reads the gif comments. - /// - private void ReadComments() - { - int flag; - - while ((flag = this.currentStream.ReadByte()) != 0) - { - if (flag > GifConstants.MaxCommentLength) - { - throw new ImageFormatException($"Gif comment length '{flag}' exceeds max '{GifConstants.MaxCommentLength}'"); - } - - byte[] buffer = new byte[flag]; - - this.currentStream.Read(buffer, 0, flag); - - this.decodedImage.Properties.Add(new ImageProperty("Comments", BitConverter.ToString(buffer))); - } - } - - /// - /// Reads an individual gif frame. - /// - private void ReadFrame() - { - GifImageDescriptor imageDescriptor = this.ReadImageDescriptor(); - - byte[] localColorTable = this.ReadFrameLocalColorTable(imageDescriptor); - - byte[] indices = this.ReadFrameIndices(imageDescriptor); - - // Determine the color table for this frame. If there is a local one, use it - // otherwise use the global color table. - byte[] colorTable = localColorTable ?? this.globalColorTable; - - this.ReadFrameColors(indices, colorTable, imageDescriptor); - - // Skip any remaining blocks - this.Skip(0); - } - - /// - /// Reads the frame indices marking the color to use for each pixel. - /// - /// The . - /// The - private byte[] ReadFrameIndices(GifImageDescriptor imageDescriptor) - { - int dataSize = this.currentStream.ReadByte(); - LzwDecoder lzwDecoder = new LzwDecoder(this.currentStream); - - byte[] indices = lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize); - - return indices; - } - - /// - /// Reads the local color table from the current frame. - /// - /// The . - /// The - private byte[] ReadFrameLocalColorTable(GifImageDescriptor imageDescriptor) - { - byte[] localColorTable = null; - - if (imageDescriptor.LocalColorTableFlag) - { - localColorTable = new byte[imageDescriptor.LocalColorTableSize * 3]; - - this.currentStream.Read(localColorTable, 0, localColorTable.Length); - } - - return localColorTable; - } - - /// - /// Reads the frames colors, mapping indices to colors. - /// - /// The indexed pixels. - /// The color table containing the available colors. - /// The - private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor) - { - int imageWidth = this.logicalScreenDescriptor.Width; - int imageHeight = this.logicalScreenDescriptor.Height; - - if (this.currentFrame == null) - { - this.currentFrame = new TColor[imageWidth * imageHeight]; - } - - TColor[] lastFrame = null; - - if (this.graphicsControlExtension != null && - this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) - { - lastFrame = new TColor[imageWidth * imageHeight]; - - Array.Copy(this.currentFrame, lastFrame, lastFrame.Length); - } - - int offset, i = 0; - int interlacePass = 0; // The interlace pass - int interlaceIncrement = 8; // The interlacing line increment - int interlaceY = 0; // The current interlaced line - - for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) - { - // Check if this image is interlaced. - int writeY; // the target y offset to write to - if (descriptor.InterlaceFlag) - { - // If so then we read lines at predetermined offsets. - // When an entire image height worth of offset lines has been read we consider this a pass. - // With each pass the number of offset lines changes and the starting line changes. - if (interlaceY >= descriptor.Height) - { - interlacePass++; - switch (interlacePass) - { - case 1: - interlaceY = 4; - break; - case 2: - interlaceY = 2; - interlaceIncrement = 4; - break; - case 3: - interlaceY = 1; - interlaceIncrement = 2; - break; - } - } - - writeY = interlaceY + descriptor.Top; - - interlaceY += interlaceIncrement; - } - else - { - writeY = y; - } - - for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) - { - offset = (writeY * imageWidth) + x; - int index = indices[i]; - - if (this.graphicsControlExtension == null || - this.graphicsControlExtension.TransparencyFlag == false || - this.graphicsControlExtension.TransparencyIndex != index) - { - // Stored in r-> g-> b-> a order. - int indexOffset = index * 3; - TColor pixel = default(TColor); - pixel.PackFromVector4(new Color(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2]).ToVector4()); - this.currentFrame[offset] = pixel; - } - - i++; - } - } - - TColor[] pixels = new TColor[imageWidth * imageHeight]; - - Array.Copy(this.currentFrame, pixels, pixels.Length); - - ImageBase currentImage; - - if (this.decodedImage.Pixels == null) - { - currentImage = this.decodedImage; - currentImage.SetPixels(imageWidth, imageHeight, pixels); - currentImage.Quality = colorTable.Length / 3; - - if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0) - { - this.decodedImage.FrameDelay = this.graphicsControlExtension.DelayTime; - } - } - else - { - ImageFrame frame = new ImageFrame(); - - currentImage = frame; - currentImage.SetPixels(imageWidth, imageHeight, pixels); - currentImage.Quality = colorTable.Length / 3; - - if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0) - { - currentImage.FrameDelay = this.graphicsControlExtension.DelayTime; - } - - this.decodedImage.Frames.Add(frame); - } - - if (this.graphicsControlExtension != null) - { - if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground) - { - for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) - { - for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) - { - offset = (y * imageWidth) + x; - - // Stored in r-> g-> b-> a order. - this.currentFrame[offset] = default(TColor); - } - } - } - else if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) - { - this.currentFrame = lastFrame; - } - } - } - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifEncoder.cs b/src/ImageSharp46/Formats/Gif/GifEncoder.cs deleted file mode 100644 index 57db04301..000000000 --- a/src/ImageSharp46/Formats/Gif/GifEncoder.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - using ImageSharp.Quantizers; - - /// - /// Image encoder for writing image data to a stream in gif format. - /// - public class GifEncoder : IImageEncoder - { - /// - /// Gets or sets the quality of output for images. - /// - /// For gifs the value ranges from 1 to 256. - public int Quality { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } = 128; - - /// - /// Gets or sets the quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - public string Extension => "gif"; - - /// - public string MimeType => "image/gif"; - - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, nameof(extension)); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - return extension.Equals(this.Extension, StringComparison.OrdinalIgnoreCase); - } - - /// - public void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - GifEncoderCore encoder = new GifEncoderCore - { - Quality = this.Quality, - Quantizer = this.Quantizer, - Threshold = this.Threshold - }; - - encoder.Encode(image, stream); - } - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp46/Formats/Gif/GifEncoderCore.cs deleted file mode 100644 index 746e27ff7..000000000 --- a/src/ImageSharp46/Formats/Gif/GifEncoderCore.cs +++ /dev/null @@ -1,349 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - using System.Linq; - using System.Threading.Tasks; - - using IO; - using Quantizers; - - /// - /// Performs the gif encoding operation. - /// - internal sealed class GifEncoderCore - { - /// - /// The number of bits requires to store the image palette. - /// - private int bitDepth; - - /// - /// Gets or sets the quality of output for images. - /// - /// For gifs the value ranges from 1 to 256. - public int Quality { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } = 128; - - /// - /// Gets or sets the quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Encodes the image to the specified stream from the . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to encode from. - /// The to encode the image data to. - public void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - if (this.Quantizer == null) - { - this.Quantizer = new OctreeQuantizer(); - } - - // Do not use IDisposable pattern here as we want to preserve the stream. - EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Little, stream); - - // Ensure that quality can be set but has a fallback. - int quality = this.Quality > 0 ? this.Quality : image.Quality; - this.Quality = quality > 0 ? quality.Clamp(1, 256) : 256; - - // Get the number of bits. - this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(this.Quality); - - // Quantize the image returning a palette. - QuantizedImage quantized = ((IQuantizer)this.Quantizer).Quantize(image, this.Quality); - - int index = GetTransparentIndex(quantized); - - // Write the header. - this.WriteHeader(writer); - - // Write the LSD. We'll use local color tables for now. - this.WriteLogicalScreenDescriptor(image, writer, index); - - // Write the first frame. - this.WriteGraphicalControlExtension(image, writer, index); - this.WriteImageDescriptor(image, writer); - this.WriteColorTable(quantized, writer); - this.WriteImageData(quantized, writer); - - // Write additional frames. - if (image.Frames.Any()) - { - this.WriteApplicationExtension(writer, image.RepeatCount, image.Frames.Count); - foreach (ImageFrame frame in image.Frames) - { - QuantizedImage quantizedFrame = ((IQuantizer)this.Quantizer).Quantize(frame, this.Quality); - - this.WriteGraphicalControlExtension(frame, writer, GetTransparentIndex(quantizedFrame)); - this.WriteImageDescriptor(frame, writer); - this.WriteColorTable(quantizedFrame, writer); - this.WriteImageData(quantizedFrame, writer); - } - } - - // TODO: Write Comments extension etc - writer.Write(GifConstants.EndIntroducer); - } - - /// - /// Returns the index of the most transparent color in the palette. - /// - /// - /// The quantized. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// - /// The . - /// - private static int GetTransparentIndex(QuantizedImage quantized) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Find the lowest alpha value and make it the transparent index. - int index = 255; - float alpha = 1; - for (int i = 0; i < quantized.Palette.Length; i++) - { - float a = quantized.Palette[i].ToVector4().W; - if (a < alpha) - { - alpha = a; - index = i; - } - } - - return index; - } - - /// - /// Writes the file header signature and version to the stream. - /// - /// The writer to write to the stream with. - private void WriteHeader(EndianBinaryWriter writer) - { - writer.Write((GifConstants.FileType + GifConstants.FileVersion).ToCharArray()); - } - - /// - /// Writes the logical screen descriptor to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The writer to write to the stream with. - /// The transparency index to set the default background index to. - private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int tranparencyIndex) - where TColor : struct, IPackedPixel - where TPacked : struct - { - GifLogicalScreenDescriptor descriptor = new GifLogicalScreenDescriptor - { - Width = (short)image.Width, - Height = (short)image.Height, - GlobalColorTableFlag = false, // Always false for now. - GlobalColorTableSize = this.bitDepth - 1, - BackgroundColorIndex = (byte)(tranparencyIndex > -1 ? tranparencyIndex : 255) - }; - - writer.Write((ushort)descriptor.Width); - writer.Write((ushort)descriptor.Height); - - PackedField field = default(PackedField); - field.SetBit(0, descriptor.GlobalColorTableFlag); // 1 : Global color table flag = 1 || 0 (GCT used/ not used) - field.SetBits(1, 3, descriptor.GlobalColorTableSize); // 2-4 : color resolution - field.SetBit(4, false); // 5 : GCT sort flag = 0 - field.SetBits(5, 3, descriptor.GlobalColorTableSize); // 6-8 : GCT size. 2^(N+1) - - // Reduce the number of writes - byte[] arr = - { - field.Byte, - descriptor.BackgroundColorIndex, // Background Color Index - descriptor.PixelAspectRatio // Pixel aspect ratio. Assume 1:1 - }; - - writer.Write(arr); - } - - /// - /// Writes the application extension to the stream. - /// - /// The writer to write to the stream with. - /// The animated image repeat count. - /// The number of image frames. - private void WriteApplicationExtension(EndianBinaryWriter writer, ushort repeatCount, int frames) - { - // Application Extension Header - if (repeatCount != 1 && frames > 0) - { - byte[] ext = - { - GifConstants.ExtensionIntroducer, - GifConstants.ApplicationExtensionLabel, - GifConstants.ApplicationBlockSize - }; - - writer.Write(ext); - - writer.Write(GifConstants.ApplicationIdentification.ToCharArray()); // NETSCAPE2.0 - writer.Write((byte)3); // Application block length - writer.Write((byte)1); // Data sub-block index (always 1) - - // 0 means loop indefinitely. Count is set as play n + 1 times. - repeatCount = (ushort)(Math.Max((ushort)0, repeatCount) - 1); - - writer.Write(repeatCount); // Repeat count for images. - - writer.Write(GifConstants.Terminator); // Terminator - } - } - - /// - /// Writes the graphics control extension to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to encode. - /// The stream to write to. - /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(ImageBase image, EndianBinaryWriter writer, int transparencyIndex) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // TODO: Check transparency logic. - bool hasTransparent = transparencyIndex > -1; - DisposalMethod disposalMethod = hasTransparent - ? DisposalMethod.RestoreToBackground - : DisposalMethod.Unspecified; - - GifGraphicsControlExtension extension = new GifGraphicsControlExtension() - { - DisposalMethod = disposalMethod, - TransparencyFlag = hasTransparent, - TransparencyIndex = transparencyIndex, - DelayTime = image.FrameDelay - }; - - // Reduce the number of writes. - byte[] intro = - { - GifConstants.ExtensionIntroducer, - GifConstants.GraphicControlLabel, - 4 // Size - }; - - writer.Write(intro); - - PackedField field = default(PackedField); - field.SetBits(3, 3, (int)extension.DisposalMethod); // 1-3 : Reserved, 4-6 : Disposal - - // TODO: Allow this as an option. - field.SetBit(6, false); // 7 : User input - 0 = none - field.SetBit(7, extension.TransparencyFlag); // 8: Has transparent. - - writer.Write(field.Byte); - writer.Write((ushort)extension.DelayTime); - writer.Write((byte)(extension.TransparencyIndex == -1 ? 255 : extension.TransparencyIndex)); - writer.Write(GifConstants.Terminator); - } - - /// - /// Writes the image descriptor to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to be encoded. - /// The stream to write to. - private void WriteImageDescriptor(ImageBase image, EndianBinaryWriter writer) - where TColor : struct, IPackedPixel - where TPacked : struct - { - writer.Write(GifConstants.ImageDescriptorLabel); // 2c - // TODO: Can we capture this? - writer.Write((ushort)0); // Left position - writer.Write((ushort)0); // Top position - writer.Write((ushort)image.Width); - writer.Write((ushort)image.Height); - - PackedField field = default(PackedField); - field.SetBit(0, true); // 1: Local color table flag = 1 (LCT used) - field.SetBit(1, false); // 2: Interlace flag 0 - field.SetBit(2, false); // 3: Sort flag 0 - field.SetBits(5, 3, this.bitDepth - 1); // 4-5: Reserved, 6-8 : LCT size. 2^(N+1) - - writer.Write(field.Byte); - } - - /// - /// Writes the color table to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to encode. - /// The writer to write to the stream with. - private void WriteColorTable(QuantizedImage image, EndianBinaryWriter writer) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Grab the palette and write it to the stream. - TColor[] palette = image.Palette; - int pixelCount = palette.Length; - - // Get max colors for bit depth. - int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; - byte[] colorTable = new byte[colorTableLength]; - - Parallel.For( - 0, - pixelCount, - i => - { - int offset = i * 3; - Color color = new Color(palette[i].ToVector4()); - - colorTable[offset] = color.R; - colorTable[offset + 1] = color.G; - colorTable[offset + 2] = color.B; - }); - - writer.Write(colorTable, 0, colorTableLength); - } - - /// - /// Writes the image pixel data to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing indexed pixels. - /// The stream to write to. - private void WriteImageData(QuantizedImage image, EndianBinaryWriter writer) - where TColor : struct, IPackedPixel - where TPacked : struct - { - byte[] indexedPixels = image.Pixels; - - LzwEncoder encoder = new LzwEncoder(indexedPixels, (byte)this.bitDepth); - encoder.Encode(writer.BaseStream); - } - } -} diff --git a/src/ImageSharp46/Formats/Gif/GifFormat.cs b/src/ImageSharp46/Formats/Gif/GifFormat.cs deleted file mode 100644 index 4c584c7ba..000000000 --- a/src/ImageSharp46/Formats/Gif/GifFormat.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Encapsulates the means to encode and decode gif images. - /// - public class GifFormat : IImageFormat - { - /// - public IImageDecoder Decoder => new GifDecoder(); - - /// - public IImageEncoder Encoder => new GifEncoder(); - } -} diff --git a/src/ImageSharp46/Formats/Gif/LzwDecoder.cs b/src/ImageSharp46/Formats/Gif/LzwDecoder.cs deleted file mode 100644 index b77d01739..000000000 --- a/src/ImageSharp46/Formats/Gif/LzwDecoder.cs +++ /dev/null @@ -1,228 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System.IO; - - /// - /// Decompresses and decodes data using the dynamic LZW algorithms. - /// - internal sealed class LzwDecoder - { - /// - /// The max decoder pixel stack size. - /// - private const int MaxStackSize = 4096; - - /// - /// The null code. - /// - private const int NullCode = -1; - - /// - /// The stream to decode. - /// - private readonly Stream stream; - - /// - /// Initializes a new instance of the class - /// and sets the stream, where the compressed data should be read from. - /// - /// The stream to read from. - /// is null. - public LzwDecoder(Stream stream) - { - Guard.NotNull(stream, nameof(stream)); - - this.stream = stream; - } - - /// - /// Decodes and decompresses all pixel indices from the stream. - /// - /// The width of the pixel index array. - /// The height of the pixel index array. - /// Size of the data. - /// The decoded and uncompressed array. - public byte[] DecodePixels(int width, int height, int dataSize) - { - Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize)); - - // The resulting index table. - byte[] pixels = new byte[width * height]; - - // Calculate the clear code. The value of the clear code is 2 ^ dataSize - int clearCode = 1 << dataSize; - - int codeSize = dataSize + 1; - - // Calculate the end code - int endCode = clearCode + 1; - - // Calculate the available code. - int availableCode = clearCode + 2; - - // Jillzhangs Code see: http://giflib.codeplex.com/ - // Adapted from John Cristy's ImageMagick. - int code; - int oldCode = NullCode; - int codeMask = (1 << codeSize) - 1; - int bits = 0; - - int[] prefix = new int[MaxStackSize]; - int[] suffix = new int[MaxStackSize]; - int[] pixelStatck = new int[MaxStackSize + 1]; - - int top = 0; - int count = 0; - int bi = 0; - int xyz = 0; - - int data = 0; - int first = 0; - - for (code = 0; code < clearCode; code++) - { - prefix[code] = 0; - suffix[code] = (byte)code; - } - - byte[] buffer = null; - while (xyz < pixels.Length) - { - if (top == 0) - { - if (bits < codeSize) - { - // Load bytes until there are enough bits for a code. - if (count == 0) - { - // Read a new data block. - buffer = this.ReadBlock(); - count = buffer.Length; - if (count == 0) - { - break; - } - - bi = 0; - } - - if (buffer != null) - { - data += buffer[bi] << bits; - } - - bits += 8; - bi++; - count--; - continue; - } - - // Get the next code - code = data & codeMask; - data >>= codeSize; - bits -= codeSize; - - // Interpret the code - if (code > availableCode || code == endCode) - { - break; - } - - if (code == clearCode) - { - // Reset the decoder - codeSize = dataSize + 1; - codeMask = (1 << codeSize) - 1; - availableCode = clearCode + 2; - oldCode = NullCode; - continue; - } - - if (oldCode == NullCode) - { - pixelStatck[top++] = suffix[code]; - oldCode = code; - first = code; - continue; - } - - int inCode = code; - if (code == availableCode) - { - pixelStatck[top++] = (byte)first; - - code = oldCode; - } - - while (code > clearCode) - { - pixelStatck[top++] = suffix[code]; - code = prefix[code]; - } - - first = suffix[code]; - - pixelStatck[top++] = suffix[code]; - - // Fix for Gifs that have "deferred clear code" as per here : - // https://bugzilla.mozilla.org/show_bug.cgi?id=55918 - if (availableCode < MaxStackSize) - { - prefix[availableCode] = oldCode; - suffix[availableCode] = first; - availableCode++; - if (availableCode == codeMask + 1 && availableCode < MaxStackSize) - { - codeSize++; - codeMask = (1 << codeSize) - 1; - } - } - - oldCode = inCode; - } - - // Pop a pixel off the pixel stack. - top--; - - // Clear missing pixels - pixels[xyz++] = (byte)pixelStatck[top]; - } - - return pixels; - } - - /// - /// Reads the next data block from the stream. A data block begins with a byte, - /// which defines the size of the block, followed by the block itself. - /// - /// - /// The . - /// - private byte[] ReadBlock() - { - int blockSize = this.stream.ReadByte(); - return this.ReadBytes(blockSize); - } - - /// - /// Reads the specified number of bytes from the data stream. - /// - /// - /// The number of bytes to read. - /// - /// - /// The . - /// - private byte[] ReadBytes(int length) - { - byte[] buffer = new byte[length]; - this.stream.Read(buffer, 0, length); - return buffer; - } - } -} diff --git a/src/ImageSharp46/Formats/Gif/LzwEncoder.cs b/src/ImageSharp46/Formats/Gif/LzwEncoder.cs deleted file mode 100644 index 003cfa834..000000000 --- a/src/ImageSharp46/Formats/Gif/LzwEncoder.cs +++ /dev/null @@ -1,419 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Encodes and compresses the image data using dynamic Lempel-Ziv compression. - /// - /// - /// Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott. K Weiner 12/00 - /// - /// GIFCOMPR.C - GIF Image compression routines - /// - /// - /// Lempel-Ziv compression based on 'compress'. GIF modifications by - /// David Rowley (mgardi@watdcsu.waterloo.edu) - /// - /// GIF Image compression - modified 'compress' - /// - /// Based on: compress.c - File compression ala IEEE Computer, June 1984. - /// By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - /// Jim McKie (decvax!mcvax!jim) - /// Steve Davies (decvax!vax135!petsd!peora!srd) - /// Ken Turkowski (decvax!decwrl!turtlevax!ken) - /// James A. Woods (decvax!ihnp4!ames!jaw) - /// Joe Orost (decvax!vax135!petsd!joe) - /// - /// - internal sealed class LzwEncoder - { - private const int Eof = -1; - - private const int Bits = 12; - - private const int HashSize = 5003; // 80% occupancy - - private readonly byte[] pixelArray; - - private readonly int initialCodeSize; - - private readonly int[] hashTable = new int[HashSize]; - - private readonly int[] codeTable = new int[HashSize]; - - private readonly int[] masks = - { - 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF - }; - - /// - /// Define the storage for the packet accumulator. - /// - private readonly byte[] accumulators = new byte[256]; - - /// - /// The current pixel - /// - private int currentPixel; - - /// - /// Number of bits/code - /// - private int bitCount; - - /// - /// User settable max # bits/code - /// - private int maxbits = Bits; - - /// - /// maximum code, given bitCount - /// - private int maxcode; - - /// - /// should NEVER generate this code - /// - private int maxmaxcode = 1 << Bits; - - /// - /// For dynamic table sizing - /// - private int hsize = HashSize; - - /// - /// First unused entry - /// - private int freeEntry; - - /// - /// Block compression parameters -- after all codes are used up, - /// and compression rate changes, start over. - /// - private bool clearFlag; - - // Algorithm: use open addressing double hashing (no chaining) on the - // prefix code / next character combination. We do a variant of Knuth's - // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime - // secondary probe. Here, the modular division first probe is gives way - // to a faster exclusive-or manipulation. Also do block compression with - // an adaptive reset, whereby the code table is cleared when the compression - // ratio decreases, but after the table fills. The variable-length output - // codes are re-sized at this point, and a special CLEAR code is generated - // for the decompressor. Late addition: construct the table according to - // file size for noticeable speed improvement on small files. Please direct - // questions about this implementation to ames!jaw. - private int globalInitialBits; - - private int clearCode; - - private int eofCode; - - // output - // - // Output the given code. - // Inputs: - // code: A bitCount-bit integer. If == -1, then EOF. This assumes - // that bitCount =< wordsize - 1. - // Outputs: - // Outputs code to the file. - // Assumptions: - // Chars are 8 bits long. - // Algorithm: - // Maintain a BITS character long buffer (so that 8 codes will - // fit in it exactly). Use the VAX insv instruction to insert each - // code in turn. When the buffer fills up empty it and start over. - private int currentAccumulator; - - private int currentBits; - - /// - /// Number of characters so far in this 'packet' - /// - private int accumulatorCount; - - /// - /// Initializes a new instance of the class. - /// - /// The array of indexed pixels. - /// The color depth in bits. - public LzwEncoder(byte[] indexedPixels, int colorDepth) - { - this.pixelArray = indexedPixels; - this.initialCodeSize = Math.Max(2, colorDepth); - } - - /// - /// Encodes and compresses the indexed pixels to the stream. - /// - /// The stream to write to. - public void Encode(Stream stream) - { - // Write "initial code size" byte - stream.WriteByte((byte)this.initialCodeSize); - - this.currentPixel = 0; - - // Compress and write the pixel data - this.Compress(this.initialCodeSize + 1, stream); - - // Write block terminator - stream.WriteByte(GifConstants.Terminator); - } - - /// - /// Gets the maximum code value - /// - /// The number of bits - /// See - private static int GetMaxcode(int bitCount) - { - return (1 << bitCount) - 1; - } - - /// - /// Add a character to the end of the current packet, and if it is 254 characters, - /// flush the packet to disk. - /// - /// The character to add. - /// The stream to write to. - private void AddCharacter(byte c, Stream stream) - { - this.accumulators[this.accumulatorCount++] = c; - if (this.accumulatorCount >= 254) - { - this.FlushPacket(stream); - } - } - - /// - /// Table clear for block compress - /// - /// The output stream. - private void ClearBlock(Stream stream) - { - this.ResetCodeTable(this.hsize); - this.freeEntry = this.clearCode + 2; - this.clearFlag = true; - - this.Output(this.clearCode, stream); - } - - /// - /// Reset the code table. - /// - /// The hash size. - private void ResetCodeTable(int size) - { - for (int i = 0; i < size; ++i) - { - this.hashTable[i] = -1; - } - } - - /// - /// Compress the packets to the stream. - /// - /// The initial bits. - /// The stream to write to. - private void Compress(int intialBits, Stream stream) - { - int fcode; - int c; - int ent; - int hsizeReg; - int hshift; - - // Set up the globals: globalInitialBits - initial number of bits - this.globalInitialBits = intialBits; - - // Set up the necessary values - this.clearFlag = false; - this.bitCount = this.globalInitialBits; - this.maxcode = GetMaxcode(this.bitCount); - - this.clearCode = 1 << (intialBits - 1); - this.eofCode = this.clearCode + 1; - this.freeEntry = this.clearCode + 2; - - this.accumulatorCount = 0; // clear packet - - ent = this.NextPixel(); - - hshift = 0; - for (fcode = this.hsize; fcode < 65536; fcode *= 2) - { - ++hshift; - } - - hshift = 8 - hshift; // set hash code range bound - - hsizeReg = this.hsize; - - this.ResetCodeTable(hsizeReg); // clear hash table - - this.Output(this.clearCode, stream); - - while ((c = this.NextPixel()) != Eof) - { - fcode = (c << this.maxbits) + ent; - int i = (c << hshift) ^ ent /* = 0 */; - - if (this.hashTable[i] == fcode) - { - ent = this.codeTable[i]; - continue; - } - - // Non-empty slot - if (this.hashTable[i] >= 0) - { - int disp = hsizeReg - i; - if (i == 0) - { - disp = 1; - } - - do - { - if ((i -= disp) < 0) - { - i += hsizeReg; - } - - if (this.hashTable[i] == fcode) - { - ent = this.codeTable[i]; - break; - } - } - while (this.hashTable[i] >= 0); - - if (this.hashTable[i] == fcode) - { - continue; - } - } - - this.Output(ent, stream); - ent = c; - if (this.freeEntry < this.maxmaxcode) - { - this.codeTable[i] = this.freeEntry++; // code -> hashtable - this.hashTable[i] = fcode; - } - else - { - this.ClearBlock(stream); - } - } - - // Put out the final code. - this.Output(ent, stream); - - this.Output(this.eofCode, stream); - } - - /// - /// Flush the packet to disk, and reset the accumulator. - /// - /// The output stream. - private void FlushPacket(Stream outStream) - { - if (this.accumulatorCount > 0) - { - outStream.WriteByte((byte)this.accumulatorCount); - outStream.Write(this.accumulators, 0, this.accumulatorCount); - this.accumulatorCount = 0; - } - } - - /// - /// Return the next pixel from the image - /// - /// - /// The - /// - private int NextPixel() - { - if (this.currentPixel == this.pixelArray.Length) - { - return Eof; - } - - if (this.currentPixel == this.pixelArray.Length) - { - return Eof; - } - - this.currentPixel++; - return this.pixelArray[this.currentPixel - 1] & 0xff; - } - - /// - /// Output the current code to the stream. - /// - /// The code. - /// The stream to write to. - private void Output(int code, Stream outs) - { - this.currentAccumulator &= this.masks[this.currentBits]; - - if (this.currentBits > 0) - { - this.currentAccumulator |= code << this.currentBits; - } - else - { - this.currentAccumulator = code; - } - - this.currentBits += this.bitCount; - - while (this.currentBits >= 8) - { - this.AddCharacter((byte)(this.currentAccumulator & 0xff), outs); - this.currentAccumulator >>= 8; - this.currentBits -= 8; - } - - // If the next entry is going to be too big for the code size, - // then increase it, if possible. - if (this.freeEntry > this.maxcode || this.clearFlag) - { - if (this.clearFlag) - { - this.maxcode = GetMaxcode(this.bitCount = this.globalInitialBits); - this.clearFlag = false; - } - else - { - ++this.bitCount; - this.maxcode = this.bitCount == this.maxbits - ? this.maxmaxcode - : GetMaxcode(this.bitCount); - } - } - - if (code == this.eofCode) - { - // At EOF, write the rest of the buffer. - while (this.currentBits > 0) - { - this.AddCharacter((byte)(this.currentAccumulator & 0xff), outs); - this.currentAccumulator >>= 8; - this.currentBits -= 8; - } - - this.FlushPacket(outs); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Gif/PackedField.cs b/src/ImageSharp46/Formats/Gif/PackedField.cs deleted file mode 100644 index cabf4f5ab..000000000 --- a/src/ImageSharp46/Formats/Gif/PackedField.cs +++ /dev/null @@ -1,199 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// Represents a byte of data in a GIF data stream which contains a number - /// of data items. - /// - internal struct PackedField : IEquatable - { - /// - /// The individual bits representing the packed byte. - /// - private static readonly bool[] Bits = new bool[8]; - - /// - /// Gets the byte which represents the data items held in this instance. - /// - public byte Byte - { - get - { - int returnValue = 0; - int bitShift = 7; - foreach (bool bit in Bits) - { - int bitValue; - if (bit) - { - bitValue = 1 << bitShift; - } - else - { - bitValue = 0; - } - - returnValue |= bitValue; - bitShift--; - } - - return Convert.ToByte(returnValue & 0xFF); - } - } - - /// - /// Returns a new with the bits in the packed fields to - /// the corresponding bits from the supplied byte. - /// - /// The value to pack. - /// The - public static PackedField FromInt(byte value) - { - PackedField packed = default(PackedField); - packed.SetBits(0, 8, value); - return packed; - } - - /// - /// Sets the specified bit within the packed fields to the supplied - /// value. - /// - /// - /// The zero-based index within the packed fields of the bit to set. - /// - /// - /// The value to set the bit to. - /// - public void SetBit(int index, bool valueToSet) - { - if (index < 0 || index > 7) - { - string message - = "Index must be between 0 and 7. Supplied index: " - + index; - throw new ArgumentOutOfRangeException(nameof(index), message); - } - - Bits[index] = valueToSet; - } - - /// - /// Sets the specified bits within the packed fields to the supplied - /// value. - /// - /// The zero-based index within the packed fields of the first bit to set. - /// The number of bits to set. - /// The value to set the bits to. - public void SetBits(int startIndex, int length, int valueToSet) - { - if (startIndex < 0 || startIndex > 7) - { - string message = $"Start index must be between 0 and 7. Supplied index: {startIndex}"; - throw new ArgumentOutOfRangeException(nameof(startIndex), message); - } - - if (length < 1 || startIndex + length > 8) - { - string message = "Length must be greater than zero and the sum of length and start index must be less than 8. " - + $"Supplied length: {length}. Supplied start index: {startIndex}"; - throw new ArgumentOutOfRangeException(nameof(length), message); - } - - int bitShift = length - 1; - for (int i = startIndex; i < startIndex + length; i++) - { - int bitValueIfSet = 1 << bitShift; - int bitValue = valueToSet & bitValueIfSet; - int bitIsSet = bitValue >> bitShift; - Bits[i] = bitIsSet == 1; - bitShift--; - } - } - - /// - /// Gets the value of the specified bit within the byte. - /// - /// The zero-based index of the bit to get. - /// - /// The value of the specified bit within the byte. - /// - public bool GetBit(int index) - { - if (index < 0 || index > 7) - { - string message = $"Index must be between 0 and 7. Supplied index: {index}"; - throw new ArgumentOutOfRangeException(nameof(index), message); - } - - return Bits[index]; - } - - /// - /// Gets the value of the specified bits within the byte. - /// - /// The zero-based index of the first bit to get. - /// The number of bits to get. - /// - /// The value of the specified bits within the byte. - /// - public int GetBits(int startIndex, int length) - { - if (startIndex < 0 || startIndex > 7) - { - string message = $"Start index must be between 0 and 7. Supplied index: {startIndex}"; - throw new ArgumentOutOfRangeException(nameof(startIndex), message); - } - - if (length < 1 || startIndex + length > 8) - { - string message = "Length must be greater than zero and the sum of length and start index must be less than 8. " - + $"Supplied length: {length}. Supplied start index: {startIndex}"; - - throw new ArgumentOutOfRangeException(nameof(length), message); - } - - int returnValue = 0; - int bitShift = length - 1; - for (int i = startIndex; i < startIndex + length; i++) - { - int bitValue = (Bits[i] ? 1 : 0) << bitShift; - returnValue += bitValue; - bitShift--; - } - - return returnValue; - } - - /// - public override bool Equals(object obj) - { - PackedField? field = obj as PackedField?; - - return this.Byte == field?.Byte; - } - - /// - public bool Equals(PackedField other) - { - return this.Byte.Equals(other.Byte); - } - - /// - public override string ToString() - { - return $"PackedField [ Byte={this.Byte} ]"; - } - - /// - public override int GetHashCode() - { - return this.Byte.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Gif/README.md b/src/ImageSharp46/Formats/Gif/README.md deleted file mode 100644 index d47a4c683..000000000 --- a/src/ImageSharp46/Formats/Gif/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Encoder/Decoder adapted and extended from: - -https://github.com/yufeih/Nine.Imaging/ -https://imagetools.codeplex.com/ diff --git a/src/ImageSharp46/Formats/Gif/Sections/GifGraphicsControlExtension.cs b/src/ImageSharp46/Formats/Gif/Sections/GifGraphicsControlExtension.cs deleted file mode 100644 index 79d98f5fb..000000000 --- a/src/ImageSharp46/Formats/Gif/Sections/GifGraphicsControlExtension.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// The Graphic Control Extension contains parameters used when - /// processing a graphic rendering block. - /// - internal sealed class GifGraphicsControlExtension - { - /// - /// Gets or sets the disposal method which indicates the way in which the - /// graphic is to be treated after being displayed. - /// - public DisposalMethod DisposalMethod { get; set; } - - /// - /// Gets or sets a value indicating whether transparency flag is to be set. - /// This indicates whether a transparency index is given in the Transparent Index field. - /// (This field is the least significant bit of the byte.) - /// - public bool TransparencyFlag { get; set; } - - /// - /// Gets or sets the transparency index. - /// The Transparency Index is such that when encountered, the corresponding pixel - /// of the display device is not modified and processing goes on to the next pixel. - /// - public int TransparencyIndex { get; set; } - - /// - /// Gets or sets the delay time. - /// If not 0, this field specifies the number of hundredths (1/100) of a second to - /// wait before continuing with the processing of the Data Stream. - /// The clock starts ticking immediately after the graphic is rendered. - /// - public int DelayTime { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Gif/Sections/GifImageDescriptor.cs b/src/ImageSharp46/Formats/Gif/Sections/GifImageDescriptor.cs deleted file mode 100644 index 12c13beaf..000000000 --- a/src/ImageSharp46/Formats/Gif/Sections/GifImageDescriptor.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Each image in the Data Stream is composed of an Image Descriptor, - /// an optional Local Color Table, and the image data. - /// Each image must fit within the boundaries of the - /// Logical Screen, as defined in the Logical Screen Descriptor. - /// - internal sealed class GifImageDescriptor - { - /// - /// Gets or sets the column number, in pixels, of the left edge of the image, - /// with respect to the left edge of the Logical Screen. - /// Leftmost column of the Logical Screen is 0. - /// - public short Left { get; set; } - - /// - /// Gets or sets the row number, in pixels, of the top edge of the image with - /// respect to the top edge of the Logical Screen. - /// Top row of the Logical Screen is 0. - /// - public short Top { get; set; } - - /// - /// Gets or sets the width of the image in pixels. - /// - public short Width { get; set; } - - /// - /// Gets or sets the height of the image in pixels. - /// - public short Height { get; set; } - - /// - /// Gets or sets a value indicating whether the presence of a Local Color Table immediately - /// follows this Image Descriptor. - /// - public bool LocalColorTableFlag { get; set; } - - /// - /// Gets or sets the local color table size. - /// If the Local Color Table Flag is set to 1, the value in this field - /// is used to calculate the number of bytes contained in the Local Color Table. - /// - public int LocalColorTableSize { get; set; } - - /// - /// Gets or sets a value indicating whether the image is to be interlaced. - /// An image is interlaced in a four-pass interlace pattern. - /// - public bool InterlaceFlag { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs b/src/ImageSharp46/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs deleted file mode 100644 index fc2cc974a..000000000 --- a/src/ImageSharp46/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// The Logical Screen Descriptor contains the parameters - /// necessary to define the area of the display device - /// within which the images will be rendered - /// - internal sealed class GifLogicalScreenDescriptor - { - /// - /// Gets or sets the width, in pixels, of the Logical Screen where the images will - /// be rendered in the displaying device. - /// - public short Width { get; set; } - - /// - /// Gets or sets the height, in pixels, of the Logical Screen where the images will be - /// rendered in the displaying device. - /// - public short Height { get; set; } - - /// - /// Gets or sets the index at the Global Color Table for the Background Color. - /// The Background Color is the color used for those - /// pixels on the screen that are not covered by an image. - /// - public byte BackgroundColorIndex { get; set; } - - /// - /// Gets or sets the pixel aspect ratio. Default to 0. - /// - public byte PixelAspectRatio { get; set; } - - /// - /// Gets or sets a value indicating whether a flag denoting the presence of a Global Color Table - /// should be set. - /// If the flag is set, the Global Color Table will immediately - /// follow the Logical Screen Descriptor. - /// - public bool GlobalColorTableFlag { get; set; } - - /// - /// Gets or sets the global color table size. - /// If the Global Color Table Flag is set to 1, - /// the value in this field is used to calculate the number of - /// bytes contained in the Global Color Table. - /// - public int GlobalColorTableSize { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/IImageDecoder.cs b/src/ImageSharp46/Formats/IImageDecoder.cs deleted file mode 100644 index 36ef23398..000000000 --- a/src/ImageSharp46/Formats/IImageDecoder.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System.IO; - - /// - /// Encapsulates properties and methods required for decoding an image from a stream. - /// - public interface IImageDecoder - { - /// - /// Gets the size of the header for this image type. - /// - /// The size of the header. - int HeaderSize { get; } - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file extension. - /// - /// True if the decoder supports the file extension; otherwise, false. - /// - bool IsSupportedFileExtension(string extension); - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file header. - /// - /// True if the decoder supports the file header; otherwise, false. - /// - bool IsSupportedFileFormat(byte[] header); - - /// - /// Decodes the image from the specified stream to the . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to decode to. - /// The containing image data. - void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct; - } -} diff --git a/src/ImageSharp46/Formats/IImageEncoder.cs b/src/ImageSharp46/Formats/IImageEncoder.cs deleted file mode 100644 index 6cb97420c..000000000 --- a/src/ImageSharp46/Formats/IImageEncoder.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System.IO; - - /// - /// Encapsulates properties and methods required for encoding an image to a stream. - /// - public interface IImageEncoder - { - /// - /// Gets or sets the quality of output for images. - /// - int Quality { get; set; } - - /// - /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains. - /// - string MimeType { get; } - - /// - /// Gets the default file extension for this encoder. - /// - string Extension { get; } - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file extension. - /// - /// True if the decoder supports the file extension; otherwise, false. - /// - bool IsSupportedFileExtension(string extension); - - /// - /// Encodes the image to the specified stream from the . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to encode from. - /// The to encode the image data to. - void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct; - } -} diff --git a/src/ImageSharp46/Formats/IImageFormat.cs b/src/ImageSharp46/Formats/IImageFormat.cs deleted file mode 100644 index cffc9861a..000000000 --- a/src/ImageSharp46/Formats/IImageFormat.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Encapsulates a supported image format, providing means to encode and decode an image. - /// - public interface IImageFormat - { - /// - /// Gets the image encoder for encoding an image from a stream. - /// - IImageEncoder Encoder { get; } - - /// - /// Gets the image decoder for decoding an image from a stream. - /// - IImageDecoder Decoder { get; } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/Bits.cs b/src/ImageSharp46/Formats/Jpg/Components/Bits.cs deleted file mode 100644 index 68278e69b..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/Bits.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Holds the unprocessed bits that have been taken from the byte-stream. - /// The n least significant bits of a form the unread bits, to be read in MSB to - /// LSB order. - /// - internal class Bits - { - /// - /// Gets or sets the accumulator. - /// - public uint Accumulator { get; set; } - - /// - /// Gets or sets the mask. - /// 0, with mask==0 when unreadbits==0.]]> - /// - public uint Mask { get; set; } - - /// - /// Gets or sets the number of unread bits in the accumulator. - /// - public int UnreadBits { get; set; } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/Components/Block.cs b/src/ImageSharp46/Formats/Jpg/Components/Block.cs deleted file mode 100644 index f41e615b5..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/Block.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System; -using System.Buffers; -using System.Runtime.CompilerServices; - -namespace ImageSharp.Formats -{ - /// - /// Represents an 8x8 block of coefficients to transform and encode. - /// - public struct Block : IDisposable - { - private static ArrayPool IntArrayPool = ArrayPool.Create(BlockSize, 50); - - /// - /// Gets the size of the block. - /// - public const int BlockSize = 64; - - /// - /// The array of block data. - /// - public int[] Data; - - /// - /// Initializes a new instance of the class. - /// - //public Block() - //{ - // this.data = new int[BlockSize]; - //} - - public void Init() - { - //this.Data = new int[BlockSize]; - this.Data = IntArrayPool.Rent(BlockSize); - } - - public static Block Create() - { - var block = new Block(); - block.Init(); - return block; - } - - public static Block[] CreateArray(int size) - { - Block[] result = new Block[size]; - for (int i = 0; i < result.Length; i++) - { - result[i].Init(); - } - return result; - } - - public bool IsInitialized => this.Data != null; - - /// - /// Gets the pixel data at the given block index. - /// - /// The index of the data to return. - /// - /// The . - /// - public int this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return this.Data[index]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set { this.Data[index] = value; } - } - - // TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement! - public void Dispose() - { - if (Data != null) - { - IntArrayPool.Return(Data, true); - Data = null; - } - } - - public static void DisposeAll(Block[] blocks) - { - for (int i = 0; i < blocks.Length; i++) - { - blocks[i].Dispose(); - } - } - - - public void Clear() - { - for (int i = 0; i < Data.Length; i++) - { - Data[i] = 0; - } - } - - public Block Clone() - { - Block clone = Create(); - Array.Copy(Data, clone.Data, BlockSize); - return clone; - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/Bytes.cs b/src/ImageSharp46/Formats/Jpg/Components/Bytes.cs deleted file mode 100644 index d4159e996..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/Bytes.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Bytes is a byte buffer, similar to a stream, except that it - /// has to be able to unread more than 1 byte, due to byte stuffing. - /// Byte stuffing is specified in section F.1.2.3. - /// - internal class Bytes - { - /// - /// Initializes a new instance of the class. - /// - public Bytes() - { - this.Buffer = new byte[4096]; - this.I = 0; - this.J = 0; - this.UnreadableBytes = 0; - } - - /// - /// Gets or sets the buffer. - /// buffer[i:j] are the buffered bytes read from the underlying - /// stream that haven't yet been passed further on. - /// - public byte[] Buffer { get; set; } - - public int I { get; set; } - - public int J { get; set; } - - /// - /// Gets or sets the unreadable bytes. The number of bytes to back up i after - /// overshooting. It can be 0, 1 or 2. - /// - public int UnreadableBytes { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/Component.cs b/src/ImageSharp46/Formats/Jpg/Components/Component.cs deleted file mode 100644 index f70dbff3f..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/Component.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Represents a single color component - /// - internal struct Component - { - /// - /// Gets or sets the horizontal sampling factor. - /// - public int HorizontalFactor; - - /// - /// Gets or sets the vertical sampling factor. - /// - public int VerticalFactor; - - /// - /// Gets or sets the identifier - /// - public byte Identifier; - - /// - /// Gets or sets the quantization table destination selector. - /// - public byte Selector; - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs deleted file mode 100644 index 13ce80f55..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Performs a fast, forward discrete cosine transform against the given block - /// decomposing it into 64 orthogonal basis signals. - /// - internal class FDCT - { - // Trigonometric constants in 13-bit fixed point format. - // TODO: Rename and describe these. - private const int fix_0_298631336 = 2446; - private const int fix_0_390180644 = 3196; - private const int fix_0_541196100 = 4433; - private const int fix_0_765366865 = 6270; - private const int fix_0_899976223 = 7373; - private const int fix_1_175875602 = 9633; - private const int fix_1_501321110 = 12299; - private const int fix_1_847759065 = 15137; - private const int fix_1_961570560 = 16069; - private const int fix_2_053119869 = 16819; - private const int fix_2_562915447 = 20995; - private const int fix_3_072711026 = 25172; - - /// - /// The number of bits - /// - private const int Bits = 13; - - /// - /// The number of bits to shift by on the first pass. - /// - private const int Pass1Bits = 2; - - /// - /// The value to shift by - /// - private const int CenterJSample = 128; - - /// - /// Performs a forward DCT on an 8x8 block of coefficients, including a level shift. - /// - /// The block of coefficients. - public static void Transform(ref Block block) - { - // Pass 1: process rows. - for (int y = 0; y < 8; y++) - { - int y8 = y * 8; - - int x0 = block[y8]; - int x1 = block[y8 + 1]; - int x2 = block[y8 + 2]; - int x3 = block[y8 + 3]; - int x4 = block[y8 + 4]; - int x5 = block[y8 + 5]; - int x6 = block[y8 + 6]; - int x7 = block[y8 + 7]; - - int tmp0 = x0 + x7; - int tmp1 = x1 + x6; - int tmp2 = x2 + x5; - int tmp3 = x3 + x4; - - int tmp10 = tmp0 + tmp3; - int tmp12 = tmp0 - tmp3; - int tmp11 = tmp1 + tmp2; - int tmp13 = tmp1 - tmp2; - - tmp0 = x0 - x7; - tmp1 = x1 - x6; - tmp2 = x2 - x5; - tmp3 = x3 - x4; - - block[y8] = (tmp10 + tmp11 - (8 * CenterJSample)) << Pass1Bits; - block[y8 + 4] = (tmp10 - tmp11) << Pass1Bits; - int z1 = (tmp12 + tmp13) * fix_0_541196100; - z1 += 1 << (Bits - Pass1Bits - 1); - block[y8 + 2] = (z1 + (tmp12 * fix_0_765366865)) >> (Bits - Pass1Bits); - block[y8 + 6] = (z1 - (tmp13 * fix_1_847759065)) >> (Bits - Pass1Bits); - - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp0 + tmp2; - tmp13 = tmp1 + tmp3; - z1 = (tmp12 + tmp13) * fix_1_175875602; - z1 += 1 << (Bits - Pass1Bits - 1); - tmp0 = tmp0 * fix_1_501321110; - tmp1 = tmp1 * fix_3_072711026; - tmp2 = tmp2 * fix_2_053119869; - tmp3 = tmp3 * fix_0_298631336; - tmp10 = tmp10 * -fix_0_899976223; - tmp11 = tmp11 * -fix_2_562915447; - tmp12 = tmp12 * -fix_0_390180644; - tmp13 = tmp13 * -fix_1_961570560; - - tmp12 += z1; - tmp13 += z1; - block[y8 + 1] = (tmp0 + tmp10 + tmp12) >> (Bits - Pass1Bits); - block[y8 + 3] = (tmp1 + tmp11 + tmp13) >> (Bits - Pass1Bits); - block[y8 + 5] = (tmp2 + tmp11 + tmp12) >> (Bits - Pass1Bits); - block[y8 + 7] = (tmp3 + tmp10 + tmp13) >> (Bits - Pass1Bits); - } - - // Pass 2: process columns. - // We remove pass1Bits scaling, but leave results scaled up by an overall factor of 8. - for (int x = 0; x < 8; x++) - { - int tmp0 = block[x] + block[56 + x]; - int tmp1 = block[8 + x] + block[48 + x]; - int tmp2 = block[16 + x] + block[40 + x]; - int tmp3 = block[24 + x] + block[32 + x]; - - int tmp10 = tmp0 + tmp3 + (1 << (Pass1Bits - 1)); - int tmp12 = tmp0 - tmp3; - int tmp11 = tmp1 + tmp2; - int tmp13 = tmp1 - tmp2; - - tmp0 = block[x] - block[56 + x]; - tmp1 = block[8 + x] - block[48 + x]; - tmp2 = block[16 + x] - block[40 + x]; - tmp3 = block[24 + x] - block[32 + x]; - - block[x] = (tmp10 + tmp11) >> Pass1Bits; - block[32 + x] = (tmp10 - tmp11) >> Pass1Bits; - - int z1 = (tmp12 + tmp13) * fix_0_541196100; - z1 += 1 << (Bits + Pass1Bits - 1); - block[16 + x] = (z1 + (tmp12 * fix_0_765366865)) >> (Bits + Pass1Bits); - block[48 + x] = (z1 - (tmp13 * fix_1_847759065)) >> (Bits + Pass1Bits); - - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp0 + tmp2; - tmp13 = tmp1 + tmp3; - z1 = (tmp12 + tmp13) * fix_1_175875602; - z1 += 1 << (Bits + Pass1Bits - 1); - tmp0 = tmp0 * fix_1_501321110; - tmp1 = tmp1 * fix_3_072711026; - tmp2 = tmp2 * fix_2_053119869; - tmp3 = tmp3 * fix_0_298631336; - tmp10 = tmp10 * -fix_0_899976223; - tmp11 = tmp11 * -fix_2_562915447; - tmp12 = tmp12 * -fix_0_390180644; - tmp13 = tmp13 * -fix_1_961570560; - - tmp12 += z1; - tmp13 += z1; - block[8 + x] = (tmp0 + tmp10 + tmp12) >> (Bits + Pass1Bits); - block[24 + x] = (tmp1 + tmp11 + tmp13) >> (Bits + Pass1Bits); - block[40 + x] = (tmp2 + tmp11 + tmp12) >> (Bits + Pass1Bits); - block[56 + x] = (tmp3 + tmp10 + tmp13) >> (Bits + Pass1Bits); - } - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/FloatIDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/FloatIDCT.cs deleted file mode 100644 index 5f2bd68b9..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/FloatIDCT.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Buffers; - -namespace ImageSharp.Formats -{ - internal class FloatIDCT - { - //private float[] _temp = new float[64]; - - // Cosine matrix and transposed cosine matrix - private static readonly float[] c = buildC(); - private static readonly float[] cT = buildCT(); - - internal FloatIDCT() - { -#if DYNAMIC_IDCT - dynamicIDCT = dynamicIDCT ?? EmitIDCT(); -#endif - } - - /// - /// Precomputes cosine terms in A.3.3 of - /// http://www.w3.org/Graphics/JPEG/itu-t81.pdf - /// - /// Closely follows the term precomputation in the - /// Java Advanced Imaging library. - /// - private static float[] buildC() - { - float[] c = new float[64]; - - for (int i = 0; i < 8; i++) // i == u or v - { - for (int j = 0; j < 8; j++) // j == x or y - { - c[i*8 + j] = i == 0 ? - 0.353553391f : /* 1 / SQRT(8) */ - (float)(0.5 * Math.Cos(((2.0 * j + 1) * i * Math.PI) / 16.0)); - } - } - - return c; - } - private static float[] buildCT() - { - // Transpose i,k <-- j,i - float[] cT = new float[64]; - for (int i = 0; i < 8; i++) - for (int j = 0; j < 8; j++) - cT[j * 8 + i] = c[i * 8 + j]; - return cT; - } - - public static void SetValueClipped(byte[,] arr, int i, int j, float val) - { - // Clip into the 0...255 range & round - arr[i, j] = val < 0 ? (byte)0 - : val > 255 ? (byte)255 - : (byte)(val + 0.5); - } - - public static void Transform(ref Block block) => FastIDCT(block.Data); - - /// See figure A.3.3 IDCT (informative) on A-5. - /// http://www.w3.org/Graphics/JPEG/itu-t81.pdf - public static void FastIDCT(int[] output) - { - //byte[,] output = new byte[8, 8]; - //int[] output = new int[64]; - - float[] _temp = ArrayPool.Shared.Rent(64); - - float[] input = ArrayPool.Shared.Rent(64); - - for (int i = 0; i < output.Length; i++) - { - input[i] = output[i]; - } - - float temp, val = 0; - int idx = 0; - for (int i = 0; i < 8; i++) - { - int i8 = i * 8; - for (int j = 0; j < 8; j++) - { - val = 0; - - for (int k = 0; k < 8; k++) - { - val += input[i8 + k] * c[k*8 + j]; - } - - _temp[idx++] = val; - } - } - for (int i = 0; i < 8; i++) - { - int i8 = i*8; - for (int j = 0; j < 8; j++) - { - temp = 128f; - - for (int k = 0; k < 8; k++) - { - temp += cT[i*8 + k] * _temp[k * 8 + j]; - } - - if (temp < 0) output[i8 + j] = 0; - else if (temp > 255) output[i8+ j] = 255; - else output[i8 + j] = (int)(temp + 0.5); // Implements rounding - } - } - - ArrayPool.Shared.Return(input, true); - ArrayPool.Shared.Return(_temp, true); - } - - - -#if DYNAMIC_IDCT - -/// -/// Generates a pure-IL nonbranching stream of instructions -/// that perform the inverse DCT. Relies on helper function -/// SetValueClipped. -/// -/// A delegate to the DynamicMethod - private static IDCTFunc EmitIDCT() - { - Type[] args = { typeof(float[]), typeof(float[]), typeof(byte[,]) }; - - DynamicMethod idctMethod = new DynamicMethod("dynamicIDCT", - null, // no return type - args); // input arrays - - ILGenerator il = idctMethod.GetILGenerator(); - - int idx = 0; - - for (int i = 0; i < 8; i++) - { - for (int j = 0; j < 8; j++) - { - il.Emit(OpCodes.Ldarg_1); // 1 {temp} - il.Emit(OpCodes.Ldc_I4_S, (short)idx++); // 3 {temp, idx} - - for (int k = 0; k < 8; k++) - { - il.Emit(OpCodes.Ldarg_0); // {in} - il.Emit(OpCodes.Ldc_I4_S, (short)(i * 8 + k)); // {in,idx} - il.Emit(OpCodes.Ldelem_R4); // {in[idx]} - il.Emit(OpCodes.Ldc_R4, c[k, j]); // {in[idx],c[k,j]} - il.Emit(OpCodes.Mul); // {in[idx]*c[k,j]} - if (k != 0) il.Emit(OpCodes.Add); - } - - il.Emit(OpCodes.Stelem_R4); // {} - } - } - - var meth = typeof(DCT).GetMethod("SetValueClipped", - BindingFlags.Static | BindingFlags.Public, null, - CallingConventions.Standard, - new Type[] { - typeof(byte[,]), // arr - typeof(int), // i - typeof(int), // j - typeof(float) } // val - , null); - - for (int i = 0; i < 8; i++) - { - for (int j = 0; j < 8; j++) - { - il.Emit(OpCodes.Ldarg_2); // {output} - il.Emit(OpCodes.Ldc_I4_S, (short)i); // {output,i} - il.Emit(OpCodes.Ldc_I4_S, (short)j); // X={output,i,j} - - il.Emit(OpCodes.Ldc_R4, 128.0f); // {X,128.0f} - - for (int k = 0; k < 8; k++) - { - il.Emit(OpCodes.Ldarg_1); // {X,temp} - il.Emit(OpCodes.Ldc_I4_S, - (short)(k * 8 + j)); // {X,temp,idx} - il.Emit(OpCodes.Ldelem_R4); // {X,temp[idx]} - il.Emit(OpCodes.Ldc_R4, cT[i, k]); // {X,temp[idx],cT[i,k]} - il.Emit(OpCodes.Mul); // {X,in[idx]*c[k,j]} - il.Emit(OpCodes.Add); - } - - il.EmitCall(OpCodes.Call, meth, null); - } - } - - il.Emit(OpCodes.Ret); - - return (IDCTFunc)idctMethod.CreateDelegate(typeof(IDCTFunc)); - } - - private delegate void IDCTFunc(float[] input, float[] temp, byte[,] output); - private static IDCTFunc dynamicIDCT = null; -#endif - - - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/Components/GrayImage.cs b/src/ImageSharp46/Formats/Jpg/Components/GrayImage.cs deleted file mode 100644 index 5f5f015ad..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/GrayImage.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Represents a grayscale image - /// - internal class GrayImage - { - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - public GrayImage(int width, int height) - { - this.Width = width; - this.Height = height; - this.Pixels = new byte[width * height]; - this.Stride = width; - this.Offset = 0; - } - - /// - /// Prevents a default instance of the class from being created. - /// - private GrayImage() - { - } - - /// - /// Gets or sets the pixels. - /// - public byte[] Pixels { get; set; } - - /// - /// Gets or sets the stride. - /// - public int Stride { get; set; } - - /// - /// Gets or sets the horizontal position. - /// - public int X { get; set; } - - /// - /// Gets or sets the vertical position. - /// - public int Y { get; set; } - - /// - /// Gets or sets the width. - /// - public int Width { get; set; } - - /// - /// Gets or sets the height. - /// - public int Height { get; set; } - - /// - /// Gets or sets the offset - /// - public int Offset { get; set; } - - /// - /// Gets an image made up of a subset of the originals pixels. - /// - /// The x-coordinate of the image. - /// The y-coordinate of the image. - /// The width. - /// The height. - /// - /// The . - /// - public GrayImage Subimage(int x, int y, int width, int height) - { - return new GrayImage - { - Width = width, - Height = height, - Pixels = this.Pixels, - Stride = this.Stride, - Offset = (y * this.Stride) + x - }; - } - - /// - /// Gets the row offset at the given position - /// - /// The y-coordinate of the image. - /// The - public int GetRowOffset(int y) - { - return this.Offset + (y * this.Stride); - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs b/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs deleted file mode 100644 index 345b45e0e..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs +++ /dev/null @@ -1,89 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System; -using System.Buffers; - -namespace ImageSharp.Formats -{ - /// - /// Represents a Huffman tree - /// - internal struct Huffman : IDisposable - { - private static ArrayPool UshortBuffer = - //ArrayPool.Shared; - ArrayPool.Create(1 << JpegDecoderCore.LutSize, 50); - - private static ArrayPool ByteBuffer = - //ArrayPool.Shared; - ArrayPool.Create(JpegDecoderCore.MaxNCodes, 50); - - private static readonly ArrayPool IntBuffer = - //ArrayPool.Shared; - ArrayPool.Create(JpegDecoderCore.MaxCodeLength, 50); - - public void Init(int lutSize, int maxNCodes, int maxCodeLength) - { - //this.Lut = new ushort[1 << lutSize]; - //this.Values = new byte[maxNCodes]; - //this.MinCodes = new int[maxCodeLength]; - //this.MaxCodes = new int[maxCodeLength]; - //this.Indices = new int[maxCodeLength]; - - this.Lut = UshortBuffer.Rent(1 << lutSize); - this.Values = ByteBuffer.Rent(maxNCodes); - this.MinCodes = IntBuffer.Rent(maxCodeLength); - this.MaxCodes = IntBuffer.Rent(maxCodeLength); ; - this.Indices = IntBuffer.Rent(maxCodeLength); ; - } - - /// - /// Gets or sets the number of codes in the tree. - /// - public int Length; - - /// - /// Gets the look-up table for the next LutSize bits in the bit-stream. - /// The high 8 bits of the uint16 are the encoded value. The low 8 bits - /// are 1 plus the code length, or 0 if the value is too large to fit in - /// lutSize bits. - /// - public ushort[] Lut; - - /// - /// Gets the the decoded values, sorted by their encoding. - /// - public byte[] Values; - - /// - /// Gets the array of minimum codes. - /// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length. - /// - public int[] MinCodes; - - /// - /// Gets the array of maximum codes. - /// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length. - /// - public int[] MaxCodes; - - /// - /// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i]. - /// - public int[] Indices; - - public void Dispose() - { - UshortBuffer.Return(Lut, true); - ByteBuffer.Return(Values, true); - IntBuffer.Return(MinCodes, true); - IntBuffer.Return(MaxCodes, true); - IntBuffer.Return(Indices, true); - } - } - - -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs deleted file mode 100644 index 88b493c4b..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Numerics; - -namespace ImageSharp.Formats -{ - /// - /// Performs a 2-D Inverse Discrete Cosine Transformation. - /// - internal class IDCT - { - private const int w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16) - private const int w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16) - private const int w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16) - private const int w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16) - private const int w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16) - private const int w7 = 565; // 2048*sqrt(2)*cos(7*pi/16) - - private const int w1pw7 = w1 + w7; - private const int w1mw7 = w1 - w7; - private const int w2pw6 = w2 + w6; - private const int w2mw6 = w2 - w6; - private const int w3pw5 = w3 + w5; - private const int w3mw5 = w3 - w5; - - private const int r2 = 181; // 256/sqrt(2) - - /// - /// Performs a 2-D Inverse Discrete Cosine Transformation. - /// - /// The input coefficients should already have been multiplied by the - /// appropriate quantization table. We use fixed-point computation, with the - /// number of bits for the fractional component varying over the intermediate - /// stages. - /// - /// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the - /// discrete W transform and for the discrete Fourier transform", IEEE Trans. on - /// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984. - /// - /// The source block of coefficients - public static void Transform(ref Block src) - { - // Horizontal 1-D IDCT. - for (int y = 0; y < 8; y++) - { - int y8 = y * 8; - - // If all the AC components are zero, then the IDCT is trivial. - if (src[y8 + 1] == 0 && src[y8 + 2] == 0 && src[y8 + 3] == 0 && - src[y8 + 4] == 0 && src[y8 + 5] == 0 && src[y8 + 6] == 0 && src[y8 + 7] == 0) - { - int dc = src[y8 + 0] << 3; - src[y8 + 0] = dc; - src[y8 + 1] = dc; - src[y8 + 2] = dc; - src[y8 + 3] = dc; - src[y8 + 4] = dc; - src[y8 + 5] = dc; - src[y8 + 6] = dc; - src[y8 + 7] = dc; - continue; - } - - // Prescale. - int x0 = (src[y8 + 0] << 11) + 128; - int x1 = src[y8 + 4] << 11; - int x2 = src[y8 + 6]; - int x3 = src[y8 + 2]; - int x4 = src[y8 + 1]; - int x5 = src[y8 + 7]; - int x6 = src[y8 + 5]; - int x7 = src[y8 + 3]; - - // Stage 1. - int x8 = w7 * (x4 + x5); - x4 = x8 + (w1mw7 * x4); - x5 = x8 - (w1pw7 * x5); - x8 = w3 * (x6 + x7); - x6 = x8 - (w3mw5 * x6); - x7 = x8 - (w3pw5 * x7); - - // Stage 2. - x8 = x0 + x1; - x0 -= x1; - x1 = w6 * (x3 + x2); - x2 = x1 - (w2pw6 * x2); - x3 = x1 + (w2mw6 * x3); - x1 = x4 + x6; - x4 -= x6; - x6 = x5 + x7; - x5 -= x7; - - // Stage 3. - x7 = x8 + x3; - x8 -= x3; - x3 = x0 + x2; - x0 -= x2; - x2 = ((r2 * (x4 + x5)) + 128) >> 8; - x4 = ((r2 * (x4 - x5)) + 128) >> 8; - - // Stage 4. - src[y8 + 0] = (x7 + x1) >> 8; - src[y8 + 1] = (x3 + x2) >> 8; - src[y8 + 2] = (x0 + x4) >> 8; - src[y8 + 3] = (x8 + x6) >> 8; - src[y8 + 4] = (x8 - x6) >> 8; - src[y8 + 5] = (x0 - x4) >> 8; - src[y8 + 6] = (x3 - x2) >> 8; - src[y8 + 7] = (x7 - x1) >> 8; - } - - // Vertical 1-D IDCT. - for (int x = 0; x < 8; x++) - { - // Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial. - // However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so - // we do not bother to check for the all-zero case. - - // Prescale. - int y0 = (src[x] << 8) + 8192; - int y1 = src[32 + x] << 8; - int y2 = src[48 + x]; - int y3 = src[16 + x]; - int y4 = src[8 + x]; - int y5 = src[56 + x]; - int y6 = src[40 + x]; - int y7 = src[24 + x]; - - // Stage 1. - int y8 = (w7 * (y4 + y5)) + 4; - y4 = (y8 + (w1mw7 * y4)) >> 3; - y5 = (y8 - (w1pw7 * y5)) >> 3; - y8 = (w3 * (y6 + y7)) + 4; - y6 = (y8 - (w3mw5 * y6)) >> 3; - y7 = (y8 - (w3pw5 * y7)) >> 3; - - // Stage 2. - y8 = y0 + y1; - y0 -= y1; - y1 = (w6 * (y3 + y2)) + 4; - y2 = (y1 - (w2pw6 * y2)) >> 3; - y3 = (y1 + (w2mw6 * y3)) >> 3; - y1 = y4 + y6; - y4 -= y6; - y6 = y5 + y7; - y5 -= y7; - - // Stage 3. - y7 = y8 + y3; - y8 -= y3; - y3 = y0 + y2; - y0 -= y2; - y2 = ((r2 * (y4 + y5)) + 128) >> 8; - y4 = ((r2 * (y4 - y5)) + 128) >> 8; - - // Stage 4. - src[x] = (y7 + y1) >> 14; - src[8 + x] = (y3 + y2) >> 14; - src[16 + x] = (y0 + y4) >> 14; - src[24 + x] = (y8 + y6) >> 14; - src[32 + x] = (y8 - y6) >> 14; - src[40 + x] = (y0 - y4) >> 14; - src[48 + x] = (y3 - y2) >> 14; - src[56 + x] = (y7 - y1) >> 14; - } - } - - } -} diff --git a/src/ImageSharp46/Formats/Jpg/Components/MagicDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/MagicDCT.cs deleted file mode 100644 index 6c71ec92e..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/MagicDCT.cs +++ /dev/null @@ -1,572 +0,0 @@ -using System; -using System.Buffers; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace ImageSharp.Formats -{ - public struct Span - where T : struct - { - public T[] Data; - public int Offset; - - public Span(int size, int offset = 0) - { - Data = new T[size]; - Offset = offset; - } - - public Span(T[] data, int offset = 0) - { - Data = data; - Offset = offset; - } - - public T this[int idx] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Data[idx + Offset]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] set { Data[idx + Offset] = value; } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span Slice(int offset) - { - return new Span(Data, Offset + offset); - } - - public static implicit operator Span(T[] data) => new Span(data, 0); - - private static readonly ArrayPool Pool = ArrayPool.Create(128, 10); - - public static Span RentFromPool(int size, int offset = 0) - { - return new Span(Pool.Rent(size), offset); - } - - public void ReturnToPool() - { - Pool.Return(Data, true); - Data = null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddOffset(int offset) - { - Offset += offset; - } - } - - public static class MagicDCT - { - private static readonly ArrayPool FloatArrayPool = ArrayPool.Create(Block.BlockSize, 50); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Matrix4x4 Load(Span src, int x, int y) - { - int b0 = y*8 + x; - y++; - int b1 = y*8 + x; - y++; - int b2 = y*8 + x; - y++; - int b3 = y*8 + x; - - return new Matrix4x4( - src[b0], src[b0 + 1], src[b0 + 2], src[b0 + 3], - src[b1], src[b1 + 1], src[b1 + 2], src[b1 + 3], - src[b2], src[b2 + 1], src[b2 + 2], src[b2 + 3], - src[b3], src[b3 + 1], src[b3 + 2], src[b3 + 3] - ); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Store(Matrix4x4 s, Span d, int x, int y) - { - int b0 = y*8 + x; - y++; - int b1 = y*8 + x; - y++; - int b2 = y*8 + x; - y++; - int b3 = y*8 + x; - - d[b0] = s.M11; - d[b0 + 1] = s.M12; - d[b0 + 2] = s.M13; - d[b0 + 3] = s.M14; - d[b1] = s.M21; - d[b1 + 1] = s.M22; - d[b1 + 2] = s.M23; - d[b1 + 3] = s.M24; - d[b2] = s.M31; - d[b2 + 1] = s.M32; - d[b2 + 2] = s.M33; - d[b2 + 3] = s.M34; - d[b3] = s.M41; - d[b3 + 1] = s.M42; - d[b3 + 2] = s.M43; - d[b3 + 3] = s.M44; - } - - public static void Transpose8x8_SSE_Slow(Span data) - { - Matrix4x4 a11 = Load(data, 0, 0); - Matrix4x4 a12 = Load(data, 4, 0); - Matrix4x4 a21 = Load(data, 0, 4); - Matrix4x4 a22 = Load(data, 4, 4); - - a11 = Matrix4x4.Transpose(a11); - a12 = Matrix4x4.Transpose(a12); - a21 = Matrix4x4.Transpose(a21); - a22 = Matrix4x4.Transpose(a22); - - Store(a11, data, 0, 0); - Store(a21, data, 4, 0); - Store(a12, data, 0, 4); - Store(a22, data, 4, 4); - } - - public static void Transpose8x8_SSE_Slow(Span src, Span dest) - { - Matrix4x4 a11 = Load(src, 0, 0); - Matrix4x4 a12 = Load(src, 4, 0); - Matrix4x4 a21 = Load(src, 0, 4); - Matrix4x4 a22 = Load(src, 4, 4); - - a11 = Matrix4x4.Transpose(a11); - a12 = Matrix4x4.Transpose(a12); - a21 = Matrix4x4.Transpose(a21); - a22 = Matrix4x4.Transpose(a22); - - Store(a11, dest, 0, 0); - Store(a21, dest, 4, 0); - Store(a12, dest, 0, 4); - Store(a22, dest, 4, 4); - } - - public static void Transpose8x8(Span data) - { - for (int i = 1; i < 8; i++) - { - int i8 = i*8; - for (int j = 0; j < i; j++) - { - float tmp = data[i8 + j]; - data[i8 + j] = data[j*8 + i]; - data[j*8 + i] = tmp; - } - } - } - - public static void Transpose8x8(Span src, Span dest) - { - for (int i = 0; i < 8; i++) - { - int i8 = i*8; - for (int j = 0; j < 8; j++) - { - dest[j*8 + i] = src[i8 + j]; - } - } - - //Matrix4x4 a11 = Load(src, 0, 0); - //Matrix4x4 a12 = Load(src, 4, 0); - //Matrix4x4 a21 = Load(src, 0, 4); - //Matrix4x4 a22 = Load(src, 4, 4); - - //a11 = Matrix4x4.Transpose(a11); - //a12 = Matrix4x4.Transpose(a12); - //a21 = Matrix4x4.Transpose(a21); - //a22 = Matrix4x4.Transpose(a22); - - //Store(a11, dest, 0, 0); - //Store(a21, dest, 4, 0); - //Store(a12, dest, 0, 4); - //Store(a22, dest, 4, 4); - } - - public static void iDCT1Dllm_32f(Span y, Span x) - { - float a0, a1, a2, a3, b0, b1, b2, b3; - float z0, z1, z2, z3, z4; - - float r0 = 1.414214f; - float r1 = 1.387040f; - float r2 = 1.306563f; - float r3 = 1.175876f; - float r4 = 1.000000f; - float r5 = 0.785695f; - float r6 = 0.541196f; - float r7 = 0.275899f; - - z0 = y[1] + y[7]; - z1 = y[3] + y[5]; - z2 = y[3] + y[7]; - z3 = y[1] + y[5]; - z4 = (z0 + z1)*r3; - - z0 = z0*(-r3 + r7); - z1 = z1*(-r3 - r1); - z2 = z2*(-r3 - r5) + z4; - z3 = z3*(-r3 + r5) + z4; - - b3 = y[7]*(-r1 + r3 + r5 - r7) + z0 + z2; - b2 = y[5]*(r1 + r3 - r5 + r7) + z1 + z3; - b1 = y[3]*(r1 + r3 + r5 - r7) + z1 + z2; - b0 = y[1]*(r1 + r3 - r5 - r7) + z0 + z3; - - z4 = (y[2] + y[6])*r6; - z0 = y[0] + y[4]; - z1 = y[0] - y[4]; - z2 = z4 - y[6]*(r2 + r6); - z3 = z4 + y[2]*(r2 - r6); - a0 = z0 + z3; - a3 = z0 - z3; - a1 = z1 + z2; - a2 = z1 - z2; - - x[0] = a0 + b0; - x[7] = a0 - b0; - x[1] = a1 + b1; - x[6] = a1 - b1; - x[2] = a2 + b2; - x[5] = a2 - b2; - x[3] = a3 + b3; - x[4] = a3 - b3; - } - - public static void iDCT2D_llm(Span s, Span d, Span temp) - { - int j; - - for (j = 0; j < 8; j++) - { - iDCT1Dllm_32f(s.Slice(j*8), temp.Slice(j*8)); - } - - Transpose8x8(temp, d); - - for (j = 0; j < 8; j++) - { - iDCT1Dllm_32f(d.Slice(j*8), temp.Slice(j*8)); - } - - Transpose8x8(temp, d); - - for (j = 0; j < 64; j++) - { - d[j] *= 0.125f; - } - } - - public static void IDCT(ref Block block) - { - Span src = Span.RentFromPool(64); - - for (int i = 0; i < 64; i++) - { - src[i] = block[i]; - } - - Span dest = Span.RentFromPool(64); - Span temp = Span.RentFromPool(64); - - //iDCT2D_llm(src, dest, temp); - //iDCT8x8GT(src, dest); - iDCT8x8_llm_sse(src, dest, temp); - - for (int i = 0; i < 64; i++) - { - block[i] = (int) (dest[i] + 0.5f); - } - - src.ReturnToPool(); - dest.ReturnToPool(); - temp.ReturnToPool(); - } - - public static void iDCT8x8GT(Span s, Span d) - { - idct81d_sse_GT(s, d); - - Transpose8x8(d); - - idct81d_sse_GT(d, d); - - Transpose8x8(d); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector4 _mm_load_ps(Span src, int offset) - { - src = src.Slice(offset); - return new Vector4(src[0], src[1], src[2], src[3]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector4 _mm_load_ps(Span src) - { - return new Vector4(src[0], src[1], src[2], src[3]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void _mm_store_ps(Span dest, int offset, Vector4 src) - { - dest = dest.Slice(offset); - dest[0] = src.X; - dest[1] = src.Y; - dest[2] = src.Z; - dest[3] = src.W; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void _mm_store_ps(Span dest, Vector4 src) - { - dest[0] = src.X; - dest[1] = src.Y; - dest[2] = src.Z; - dest[3] = src.W; - } - - - public static void idct81d_sse_GT(Span src, Span dst) - { - Vector4 c1414 = new Vector4(1.4142135623731f); - Vector4 c0250 = new Vector4(0.25f); - Vector4 c0353 = new Vector4(0.353553390593274f); - Vector4 c0707 = new Vector4(0.707106781186547f); - - for (int i = 0; i < 2; i++) - { - Vector4 ms0 = _mm_load_ps(src, 0); - Vector4 ms1 = _mm_load_ps(src, 8); - Vector4 ms2 = _mm_load_ps(src, 16); - Vector4 ms3 = _mm_load_ps(src, 24); - Vector4 ms4 = _mm_load_ps(src, 32); - Vector4 ms5 = _mm_load_ps(src, 40); - Vector4 ms6 = _mm_load_ps(src, 48); - Vector4 ms7 = _mm_load_ps(src, 56); - - Vector4 mx00 = (c1414*ms0); - - Vector4 mx01 = ((new Vector4(1.38703984532215f)*ms1) + (new Vector4(0.275899379282943f)*ms7)); - Vector4 mx02 = ((new Vector4(1.30656296487638f)*ms2) + (new Vector4(0.541196100146197f)*ms6)); - Vector4 mx03 = ((new Vector4(1.17587560241936f)*ms3) + (new Vector4(0.785694958387102f)*ms5)); - - Vector4 mx04 = (c1414*ms4); - - Vector4 mx05 = ((new Vector4(-0.785694958387102f)*ms3) + (new Vector4(+1.17587560241936f)*ms5)); - Vector4 mx06 = ((new Vector4(0.541196100146197f)*ms2) + (new Vector4(-1.30656296487638f)*ms6)); - Vector4 mx07 = ((new Vector4(-0.275899379282943f)*ms1) + (new Vector4(1.38703984532215f)*ms7)); - Vector4 mx09 = (mx00 + mx04); - Vector4 mx0a = (mx01 + mx03); - - Vector4 mx0b = (c1414*mx02); - - Vector4 mx0c = (mx00 - mx04); - Vector4 mx0d = (mx01 - mx03); - - Vector4 mx0e = (c0353*(mx09 - mx0b)); - Vector4 mx0f = (c0353*(mx0c - mx0d)); - Vector4 mx10 = (c0353*(mx0c - mx0d)); - Vector4 mx11 = (c1414*mx06); - - Vector4 mx12 = (mx05 + mx07); - - Vector4 mx13 = (mx05 - mx07); - - Vector4 mx14 = (c0353*(mx11 + mx12)); - Vector4 mx15 = (c0353*(mx11 - mx12)); - Vector4 mx16 = (new Vector4(0.5f)*mx13); - - _mm_store_ps(dst, 0, ((c0250 + (mx09 + mx0b))*(c0353*mx0a))); - _mm_store_ps(dst, 8, (c0707*(mx0f + mx15))); - _mm_store_ps(dst, 16, (c0707*(mx0f - mx15))); - _mm_store_ps(dst, 24, (c0707*(mx0e + mx16))); - _mm_store_ps(dst, 32, (c0707*(mx0e - mx16))); - _mm_store_ps(dst, 40, (c0707*(mx10 - mx14))); - _mm_store_ps(dst, 48, (c0707*(mx10 + mx14))); - - _mm_store_ps(dst, 56, ((c0250*(mx09 + mx0b)) - (c0353*mx0a))); - - dst = dst.Slice(4); - src = src.Slice(4); - } - } - - private static readonly Vector4 _1_175876 = new Vector4(1.175876f); - private static readonly Vector4 _1_961571 = new Vector4(-1.961571f); - private static readonly Vector4 _0_390181 = new Vector4(-0.390181f); - private static readonly Vector4 _0_899976 = new Vector4(-0.899976f); - private static readonly Vector4 _2_562915 = new Vector4(-2.562915f); - private static readonly Vector4 _0_298631 = new Vector4(0.298631f); - private static readonly Vector4 _2_053120 = new Vector4(2.053120f); - private static readonly Vector4 _3_072711 = new Vector4(3.072711f); - private static readonly Vector4 _1_501321 = new Vector4(1.501321f); - private static readonly Vector4 _0_541196 = new Vector4(0.541196f); - private static readonly Vector4 _1_847759 = new Vector4(-1.847759f); - private static readonly Vector4 _0_765367 = new Vector4(0.765367f); - - public static void iDCT2D8x4_32f(Span y, Span x) - { - /* - float a0,a1,a2,a3,b0,b1,b2,b3; float z0,z1,z2,z3,z4; float r[8]; int i; - for(i = 0;i < 8;i++){ r[i] = (float)(cos((double)i / 16.0 * M_PI) * M_SQRT2); } - */ - /* - 0: 1.414214 - 1: 1.387040 - 2: 1.306563 - 3: - 4: 1.000000 - 5: 0.785695 - 6: - 7: 0.275899 - */ - Vector4 my1 = _mm_load_ps(y, 8); - Vector4 my7 = _mm_load_ps(y, 56); - Vector4 mz0 = my1 + my7; - - Vector4 my3 = _mm_load_ps(y, 24); - Vector4 mz2 = my3 + my7; - Vector4 my5 = _mm_load_ps(y, 40); - Vector4 mz1 = my3 + my5; - Vector4 mz3 = my1 + my5; - - Vector4 mz4 = ((mz0 + mz1)* _1_175876); - //z0 = y[1] + y[7]; z1 = y[3] + y[5]; z2 = y[3] + y[7]; z3 = y[1] + y[5]; - //z4 = (z0 + z1) * r[3]; - - mz2 = mz2* _1_961571 + mz4; - mz3 = mz3* _0_390181 + mz4; - mz0 = mz0* _0_899976; - mz1 = mz1* _2_562915; - - /* - -0.899976 - -2.562915 - -1.961571 - -0.390181 - z0 = z0 * (-r[3] + r[7]); - z1 = z1 * (-r[3] - r[1]); - z2 = z2 * (-r[3] - r[5]) + z4; - z3 = z3 * (-r[3] + r[5]) + z4;*/ - - - Vector4 mb3 = my7* _0_298631 + mz0 + mz2; - Vector4 mb2 = my5* _2_053120 + mz1 + mz3; - Vector4 mb1 = my3* _3_072711 + mz1 + mz2; - Vector4 mb0 = my1* _1_501321 + mz0 + mz3; - - /* - 0.298631 - 2.053120 - 3.072711 - 1.501321 - b3 = y[7] * (-r[1] + r[3] + r[5] - r[7]) + z0 + z2; - b2 = y[5] * ( r[1] + r[3] - r[5] + r[7]) + z1 + z3; - b1 = y[3] * ( r[1] + r[3] + r[5] - r[7]) + z1 + z2; - b0 = y[1] * ( r[1] + r[3] - r[5] - r[7]) + z0 + z3; - */ - - Vector4 my2 = _mm_load_ps(y, 16); - Vector4 my6 = _mm_load_ps(y, 48); - mz4 = (my2 + my6)* _0_541196; - Vector4 my0 = _mm_load_ps(y, 0); - Vector4 my4 = _mm_load_ps(y, 32); - mz0 = my0 + my4; - mz1 = my0 - my4; - - mz2 = mz4 + my6* _1_847759; - mz3 = mz4 + my2* _0_765367; - - my0 = mz0 + mz3; - my3 = mz0 - mz3; - my1 = mz1 + mz2; - my2 = mz1 - mz2; - /* - 1.847759 - 0.765367 - z4 = (y[2] + y[6]) * r[6]; - z0 = y[0] + y[4]; z1 = y[0] - y[4]; - z2 = z4 - y[6] * (r[2] + r[6]); - z3 = z4 + y[2] * (r[2] - r[6]); - a0 = z0 + z3; a3 = z0 - z3; - a1 = z1 + z2; a2 = z1 - z2; - */ - - _mm_store_ps(x, 0, my0 + mb0); - - _mm_store_ps(x, 56, my0 - mb0); - - _mm_store_ps(x, 8, my1 + mb1); - - _mm_store_ps(x, 48, my1 - mb1); - - _mm_store_ps(x, 16, my2 + mb2); - - _mm_store_ps(x, 40, my2 - mb2); - - _mm_store_ps(x, 24, my3 + mb3); - - _mm_store_ps(x, 32, my3 - mb3); - /* - x[0] = a0 + b0; x[7] = a0 - b0; - x[1] = a1 + b1; x[6] = a1 - b1; - x[2] = a2 + b2; x[5] = a2 - b2; - x[3] = a3 + b3; x[4] = a3 - b3; - for(i = 0;i < 8;i++){ x[i] *= 0.353554f; } - */ - } - - public static void iDCT8x8_llm_sse(Span s, Span d, Span temp) - { - Transpose8x8(s, temp); - iDCT2D8x4_32f(temp, d); - - iDCT2D8x4_32f(temp.Slice(4), d.Slice(4)); - - Transpose8x8(d, temp); - - iDCT2D8x4_32f(temp, d); - - iDCT2D8x4_32f(temp.Slice(4), d.Slice(4)); - - Vector4 c = new Vector4(0.1250f); - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//0 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//1 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//2 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//3 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//4 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//5 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//6 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//7 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//8 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//9 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//10 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//11 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//12 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//13 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//14 - - _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//15 - } -} -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/Components/YCbCrImage.cs b/src/ImageSharp46/Formats/Jpg/Components/YCbCrImage.cs deleted file mode 100644 index 564da379b..000000000 --- a/src/ImageSharp46/Formats/Jpg/Components/YCbCrImage.cs +++ /dev/null @@ -1,228 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Represents an image made up of three color components (luminance, blue chroma, red chroma) - /// - internal class YCbCrImage - { - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - /// The ratio. - public YCbCrImage(int width, int height, YCbCrSubsampleRatio ratio) - { - int cw, ch; - YCbCrSize(width, height, ratio, out cw, out ch); - this.YChannel = new byte[width * height]; - this.CbChannel = new byte[cw * ch]; - this.CrChannel = new byte[cw * ch]; - this.Ratio = ratio; - this.YStride = width; - this.CStride = cw; - this.X = 0; - this.Y = 0; - this.Width = width; - this.Height = height; - } - - /// - /// Prevents a default instance of the class from being created. - /// - private YCbCrImage() - { - } - - /// - /// Provides enumeration of the various available subsample ratios. - /// - public enum YCbCrSubsampleRatio - { - YCbCrSubsampleRatio444, - - YCbCrSubsampleRatio422, - - YCbCrSubsampleRatio420, - - YCbCrSubsampleRatio440, - - YCbCrSubsampleRatio411, - - YCbCrSubsampleRatio410, - } - - /// - /// Gets or sets the luminance components channel. - /// - public byte[] YChannel { get; set; } - - /// - /// Gets or sets the blue chroma components channel. - /// - public byte[] CbChannel { get; set; } - - /// - /// Gets or sets the red chroma components channel. - /// - public byte[] CrChannel { get; set; } - - /// - /// Gets or sets the Y slice index delta between vertically adjacent pixels. - /// - public int YStride { get; set; } - - /// - /// Gets or sets the red and blue chroma slice index delta between vertically adjacent pixels - /// that map to separate chroma samples. - /// - public int CStride { get; set; } - - /// - /// Gets or sets the index of the first luminance element. - /// - public int YOffset { get; set; } - - /// - /// Gets or sets the index of the first element of red or blue chroma. - /// - public int COffset { get; set; } - - /// - /// Gets or sets the horizontal position. - /// - public int X { get; set; } - - /// - /// Gets or sets the vertical position. - /// - public int Y { get; set; } - - /// - /// Gets or sets the width. - /// - public int Width { get; set; } - - /// - /// Gets or sets the height. - /// - public int Height { get; set; } - - /// - /// Gets or sets the subsampling ratio. - /// - public YCbCrSubsampleRatio Ratio { get; set; } - - /// - /// Gets an image made up of a subset of the originals pixels. - /// - /// The x-coordinate of the image. - /// The y-coordinate of the image. - /// The width. - /// The height. - /// - /// The . - /// - public YCbCrImage Subimage(int x, int y, int width, int height) - { - YCbCrImage ret = new YCbCrImage - { - Width = width, - Height = height, - YChannel = this.YChannel, - CbChannel = this.CbChannel, - CrChannel = this.CrChannel, - Ratio = this.Ratio, - YStride = this.YStride, - CStride = this.CStride, - YOffset = (y * this.YStride) + x, - COffset = (y * this.CStride) + x - }; - return ret; - } - - /// - /// Returns the offset of the first luminance component at the given row - /// - /// The row number. - /// - /// The . - /// - public int GetRowYOffset(int y) - { - return y * this.YStride; - } - - /// - /// Returns the offset of the first chroma component at the given row - /// - /// The row number. - /// - /// The . - /// - public int GetRowCOffset(int y) - { - switch (this.Ratio) - { - case YCbCrSubsampleRatio.YCbCrSubsampleRatio422: - return y * this.CStride; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio420: - return (y / 2) * this.CStride; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio440: - return (y / 2) * this.CStride; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio411: - return y * this.CStride; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio410: - return (y / 2) * this.CStride; - default: - return y * this.CStride; - } - } - - /// - /// Returns the height and width of the chroma components - /// - /// The width. - /// The height. - /// The subsampling ratio. - /// The chroma width. - /// The chroma height. - private static void YCbCrSize(int width, int height, YCbCrSubsampleRatio ratio, out int chromaWidth, out int chromaHeight) - { - switch (ratio) - { - case YCbCrSubsampleRatio.YCbCrSubsampleRatio422: - chromaWidth = (width + 1) / 2; - chromaHeight = height; - break; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio420: - chromaWidth = (width + 1) / 2; - chromaHeight = (height + 1) / 2; - break; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio440: - chromaWidth = width; - chromaHeight = (height + 1) / 2; - break; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio411: - chromaWidth = (width + 3) / 4; - chromaHeight = height; - break; - case YCbCrSubsampleRatio.YCbCrSubsampleRatio410: - chromaWidth = (width + 3) / 4; - chromaHeight = (height + 1) / 2; - break; - default: - - // Default to 4:4:4 subsampling. - chromaWidth = width; - chromaHeight = height; - break; - } - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegConstants.cs b/src/ImageSharp46/Formats/Jpg/JpegConstants.cs deleted file mode 100644 index 19d726e70..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegConstants.cs +++ /dev/null @@ -1,230 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Defines jpeg constants defined in the specification. - /// - internal static class JpegConstants - { - /// - /// The maximum allowable length in each dimension of a jpeg image. - /// - public const ushort MaxLength = 65535; - - /// - /// Represents high detail chroma horizontal subsampling. - /// - public static readonly byte[] ChromaFourFourFourHorizontal = { 0x11, 0x11, 0x11 }; - - /// - /// Represents high detail chroma vertical subsampling. - /// - public static readonly byte[] ChromaFourFourFourVertical = { 0x11, 0x11, 0x11 }; - - /// - /// Represents medium detail chroma vertical subsampling. - /// - public static readonly byte[] ChromaFourTwoTwoVertical = { 0x11, 0x11, 0x11 }; - - /// - /// Represents low detail chroma vertical subsampling. - /// - public static readonly byte[] ChromaFourTwoZeroVertical = { 0x22, 0x11, 0x11 }; - - /// - /// Represents medium detail chroma horizontal subsampling. - /// - public static readonly byte[] ChromaFourTwoTwoHorizontal = { 0x22, 0x11, 0x11 }; - - /// - /// Represents low detail chroma horizontal subsampling. - /// - public static readonly byte[] ChromaFourTwoZeroHorizontal = { 0x22, 0x11, 0x11 }; - - /// - /// Describes component ids for start of frame components. - /// - internal static class Components - { - /// - /// The YCbCr luminance component id. - /// - public const byte Y = 1; - - /// - /// The YCbCr chroma component id. - /// - public const byte Cb = 2; - - /// - /// The YCbCr chroma component id. - /// - public const byte Cr = 3; - - /// - /// The YIQ x coordinate component id. - /// - public const byte I = 4; - - /// - /// The YIQ y coordinate component id. - /// - public const byte Q = 5; - } - - /// - /// Describes common Jpeg markers - /// - internal static class Markers - { - /// - /// Marker prefix. Next byte is a marker. - /// - public const byte XFF = 0xff; - - /// - /// Start of Image - /// - public const byte SOI = 0xd8; - - /// - /// Start of Frame (baseline DCT) - /// - /// Indicates that this is a baseline DCT-based JPEG, and specifies the width, height, number of components, - /// and component subsampling (e.g., 4:2:0). - /// - /// - public const byte SOF0 = 0xc0; - - /// - /// Start Of Frame (Extended Sequential DCT) - /// - /// Indicates that this is a progressive DCT-based JPEG, and specifies the width, height, number of components, - /// and component subsampling (e.g., 4:2:0). - /// - /// - public const byte SOF1 = 0xc1; - - /// - /// Start Of Frame (progressive DCT) - /// - /// Indicates that this is a progressive DCT-based JPEG, and specifies the width, height, number of components, - /// and component subsampling (e.g., 4:2:0). - /// - /// - public const byte SOF2 = 0xc2; - - /// - /// Define Huffman Table(s) - /// - /// Specifies one or more Huffman tables. - /// - /// - public const byte DHT = 0xc4; - - /// - /// Define Quantization Table(s) - /// - /// Specifies one or more quantization tables. - /// - /// - public const byte DQT = 0xdb; - - /// - /// Define Restart Interval - /// - /// Specifies the interval between RSTn markers, in macroblocks. This marker is followed by two bytes - /// indicating the fixed size so it can be treated like any other variable size segment. - /// - /// - public const byte DRI = 0xdd; - - /// - /// Define First Restart - /// - /// Inserted every r macroblocks, where r is the restart interval set by a DRI marker. - /// Not used if there was no DRI marker. The low three bits of the marker code cycle in value from 0 to 7. - /// - /// - public const byte RST0 = 0xd0; - - /// - /// Define Eigth Restart - /// - /// Inserted every r macroblocks, where r is the restart interval set by a DRI marker. - /// Not used if there was no DRI marker. The low three bits of the marker code cycle in value from 0 to 7. - /// - /// - public const byte RST7 = 0xd7; - - /// - /// Start of Scan - /// - /// Begins a top-to-bottom scan of the image. In baseline DCT JPEG images, there is generally a single scan. - /// Progressive DCT JPEG images usually contain multiple scans. This marker specifies which slice of data it - /// will contain, and is immediately followed by entropy-coded data. - /// - /// - public const byte SOS = 0xda; - - /// - /// Comment - /// - /// Contains a text comment. - /// - /// - public const byte COM = 0xfe; - - /// - /// End of Image - /// - public const byte EOI = 0xd9; - - /// - /// Application specific marker for marking the jpeg format. - /// - /// - public const byte APP0 = 0xe0; - - /// - /// Application specific marker for marking where to store metadata. - /// - public const byte APP1 = 0xe1; - - /// - /// Application specific marker used by Adobe for storing encoding information for DCT filters. - /// - public const byte APP14 = 0xee; - - /// - /// Application specific marker used by GraphicConverter to store JPEG quality. - /// - public const byte APP15 = 0xef; - } - - /// - /// Describes Adobe specific markers - /// - internal static class Adobe - { - /// - /// The color transform is unknown.(RGB or CMYK) - /// - public const int ColorTransformUnknown = 0; - - /// - /// The color transform is YCbCr (luminance, red chroma, blue chroma) - /// - public const int ColorTransformYCbCr = 1; - - /// - /// The color transform is YCCK (luminance, red chroma, blue chroma, keyline) - /// - public const int ColorTransformYcck = 2; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs deleted file mode 100644 index d3c64a9c0..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs +++ /dev/null @@ -1,141 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Image decoder for generating an image out of a jpg stream. - /// - public class JpegDecoder : IImageDecoder - { - /// - /// Gets the size of the header for this image type. - /// - /// The size of the header. - public int HeaderSize => 11; - - /// - /// Indicates if the image decoder supports the specified - /// file extension. - /// - /// The file extension. - /// - /// true, if the decoder supports the specified - /// extensions; otherwise false. - /// - /// - /// is null (Nothing in Visual Basic). - /// is a string - /// of length zero or contains only blanks. - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, "extension"); - - if (extension.StartsWith(".")) - { - extension = extension.Substring(1); - } - - return extension.Equals("JPG", StringComparison.OrdinalIgnoreCase) || - extension.Equals("JPEG", StringComparison.OrdinalIgnoreCase) || - extension.Equals("JFIF", StringComparison.OrdinalIgnoreCase); - } - - /// - /// Indicates if the image decoder supports the specified - /// file header. - /// - /// The file header. - /// - /// true, if the decoder supports the specified - /// file header; otherwise false. - /// - /// - /// is null (Nothing in Visual Basic). - public bool IsSupportedFileFormat(byte[] header) - { - Guard.NotNull(header, "header"); - - bool isSupported = false; - - if (header.Length >= 11) - { - bool isJfif = IsJfif(header); - bool isExif = IsExif(header); - bool isJpeg = IsJpeg(header); - - isSupported = isJfif || isExif || isJpeg; - } - - return isSupported; - } - - /// - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, "image"); - Guard.NotNull(stream, "stream"); - - using (JpegDecoderCore decoder = new JpegDecoderCore()) - { - decoder.Decode(image, stream, false); - } - } - - /// - /// Returns a value indicating whether the given bytes identify Jfif data. - /// - /// The bytes representing the file header. - /// The - private static bool IsJfif(byte[] header) - { - bool isJfif = - header[6] == 0x4A && // J - header[7] == 0x46 && // F - header[8] == 0x49 && // I - header[9] == 0x46 && // F - header[10] == 0x00; - - return isJfif; - } - - /// - /// Returns a value indicating whether the given bytes identify EXIF data. - /// - /// The bytes representing the file header. - /// The - private static bool IsExif(byte[] header) - { - bool isExif = - header[6] == 0x45 && // E - header[7] == 0x78 && // X - header[8] == 0x69 && // I - header[9] == 0x66 && // F - header[10] == 0x00; - - return isExif; - } - - /// - /// Returns a value indicating whether the given bytes identify Jpeg data. - /// This is a last chance resort for jpegs that contain ICC information. - /// - /// The bytes representing the file header. - /// The - private static bool IsJpeg(byte[] header) - { - bool isJpg = - header[0] == 0xFF && // 255 - header[1] == 0xD8; // 216 - - return isJpg; - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs deleted file mode 100644 index 2f0b22829..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs +++ /dev/null @@ -1,2282 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Runtime.CompilerServices; - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - using System.Threading.Tasks; - - /// - /// Performs the jpeg decoding operation. - /// - internal class JpegDecoderCore : IDisposable - { - /// - /// The maximum (inclusive) number of bits in a Huffman code. - /// - internal const int MaxCodeLength = 16; - - /// - /// The maximum (inclusive) number of codes in a Huffman tree. - /// - internal const int MaxNCodes = 256; - - /// - /// The log-2 size of the Huffman decoder's look-up table. - /// - internal const int LutSize = 8; - - /// - /// The maximum number of color components - /// - private const int MaxComponents = 4; - - /// - /// The maximum number of Huffman table classes - /// - private const int MaxTc = 1; - - /// - /// The maximum number of Huffman table identifiers - /// - private const int MaxTh = 3; - - private const int ThRowSize = MaxTh + 1; - - /// - /// The maximum number of quantization tables - /// - private const int MaxTq = 3; - - /// - /// The DC table index - /// - private const int DcTable = 0; - - /// - /// The AC table index - /// - private const int AcTable = 1; - - /// - /// Unzig maps from the zigzag ordering to the natural ordering. For example, - /// unzig[3] is the column and row of the fourth element in zigzag order. The - /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). - /// - private static readonly int[] Unzig = - { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, - 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, - 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, - 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, - }; - - /// - /// The component array - /// - private readonly Component[] componentArray; - - /// - /// Saved state between progressive-mode scans. - /// - private readonly Block[][] progCoeffs; - - /// - /// The huffman trees - /// - //private readonly Huffman[,] huffmanTrees; - - private readonly Huffman[] huffmanTrees; - - /// - /// Quantization tables, in zigzag order. - /// - private readonly Block[] quantizationTables; - - /// - /// A temporary buffer for holding pixels - /// - private readonly byte[] temp; - - /// - /// The byte buffer. - /// - private readonly Bytes bytes; - - /// - /// The image width - /// - private int imageWidth; - - /// - /// The image height - /// - private int imageHeight; - - /// - /// The number of color components within the image. - /// - private int componentCount; - - /// - /// A grayscale image to decode to. - /// - private GrayImage grayImage; - - /// - /// The full color image to decode to. - /// - private YCbCrImage ycbcrImage; - - /// - /// The input stream. - /// - private Stream inputStream; - - /// - /// Holds the unprocessed bits that have been taken from the byte-stream. - /// - private Bits bits; - - /// - /// The array of keyline pixels in a CMYK image - /// - private byte[] blackPixels; - - /// - /// The width in bytes or a single row of keyline pixels in a CMYK image - /// - private int blackStride; - - /// - /// The restart interval - /// - private int restartInterval; - - /// - /// Whether the image is interlaced (progressive) - /// - private bool isProgressive; - - /// - /// Whether the image has a JFIF header - /// - private bool isJfif; - - /// - /// Whether the image is in CMYK format with an App14 marker - /// - private bool adobeTransformValid; - - /// - /// The App14 marker color-space - /// - private byte adobeTransform; - - /// - /// End-of-Band run, specified in section G.1.2.2. - /// - private ushort eobRun; - - /// - /// The horizontal resolution. Calculated if the image has a JFIF header. - /// - private short horizontalResolution; - - /// - /// The vertical resolution. Calculated if the image has a JFIF header. - /// - private short verticalResolution; - - private int blockIndex; - - /// - /// Initializes a new instance of the class. - /// - public JpegDecoderCore() - { - //this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1]; - this.huffmanTrees = new Huffman[(MaxTc + 1)*(MaxTh + 1)]; - - this.quantizationTables = Block.CreateArray(MaxTq + 1); - this.temp = new byte[2 * Block.BlockSize]; - this.componentArray = new Component[MaxComponents]; - this.progCoeffs = new Block[MaxComponents][]; - this.bits = new Bits(); - this.bytes = new Bytes(); - - // TODO: This looks like it could be static. - - for (int i = 0; i < MaxTc + 1; i++) - { - for (int j = 0; j < MaxTh + 1; j++) - { - //this.huffmanTrees[i, j].Init(LutSize, MaxNCodes, MaxCodeLength); - this.huffmanTrees[i* ThRowSize + j].Init(LutSize, MaxNCodes, MaxCodeLength); - } - } - - //for (int i = 0; i < this.quantizationTables.Length; i++) - //{ - // //this.quantizationTables[i] = new Block(); - // this.quantizationTables[i].Init(); - //} - - //for (int i = 0; i < this.componentArray.Length; i++) - //{ - // this.componentArray[i] = new Component(); - //} - } - - - /// - /// Decodes the image from the specified this._stream and sets - /// the data to image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image, where the data should be set to. - /// The stream, where the image should be. - /// Whether to decode metadata only. - public void Decode(Image image, Stream stream, bool configOnly) - where TColor : struct, IPackedPixel - where TPacked : struct - { - this.inputStream = stream; - - // Check for the Start Of Image marker. - this.ReadFull(this.temp, 0, 2); - if (this.temp[0] != JpegConstants.Markers.XFF || this.temp[1] != JpegConstants.Markers.SOI) - { - throw new ImageFormatException("Missing SOI marker."); - } - - // Process the remaining segments until the End Of Image marker. - while (true) - { - this.ReadFull(this.temp, 0, 2); - while (this.temp[0] != 0xff) - { - // Strictly speaking, this is a format error. However, libjpeg is - // liberal in what it accepts. As of version 9, next_marker in - // jdmarker.c treats this as a warning (JWRN_EXTRANEOUS_DATA) and - // continues to decode the stream. Even before next_marker sees - // extraneous data, jpeg_fill_bit_buffer in jdhuff.c reads as many - // bytes as it can, possibly past the end of a scan's data. It - // effectively puts back any markers that it overscanned (e.g. an - // "\xff\xd9" EOI marker), but it does not put back non-marker data, - // and thus it can silently ignore a small number of extraneous - // non-marker bytes before next_marker has a chance to see them (and - // print a warning). - // We are therefore also liberal in what we accept. Extraneous data - // is silently ignore - // This is similar to, but not exactly the same as, the restart - // mechanism within a scan (the RST[0-7] markers). - // Note that extraneous 0xff bytes in e.g. SOS data are escaped as - // "\xff\x00", and so are detected a little further down below. - this.temp[0] = this.temp[1]; - this.temp[1] = this.ReadByte(); - } - - byte marker = this.temp[1]; - if (marker == 0) - { - // Treat "\xff\x00" as extraneous data. - continue; - } - - while (marker == 0xff) - { - // Section B.1.1.2 says, "Any marker may optionally be preceded by any - // number of fill bytes, which are bytes assigned code X'FF'". - marker = this.ReadByte(); - } - - // End Of Image. - if (marker == JpegConstants.Markers.EOI) - { - break; - } - - if (JpegConstants.Markers.RST0 <= marker && marker <= JpegConstants.Markers.RST7) - { - // Figures B.2 and B.16 of the specification suggest that restart markers should - // only occur between Entropy Coded Segments and not after the final ECS. - // However, some encoders may generate incorrect JPEGs with a final restart - // marker. That restart marker will be seen here instead of inside the ProcessSOS - // method, and is ignored as a harmless error. Restart markers have no extra data, - // so we check for this before we read the 16-bit length of the segment. - continue; - } - - // Read the 16-bit length of the segment. The value includes the 2 bytes for the - // length itself, so we subtract 2 to get the number of remaining bytes. - this.ReadFull(this.temp, 0, 2); - int remaining = (this.temp[0] << 8) + this.temp[1] - 2; - if (remaining < 0) - { - throw new ImageFormatException("Short segment length."); - } - - switch (marker) - { - case JpegConstants.Markers.SOF0: - case JpegConstants.Markers.SOF1: - case JpegConstants.Markers.SOF2: - this.isProgressive = marker == JpegConstants.Markers.SOF2; - this.ProcessStartOfFrameMarker(remaining); - if (configOnly && this.isJfif) - { - return; - } - - break; - case JpegConstants.Markers.DHT: - if (configOnly) - { - this.Skip(remaining); - } - else - { - this.ProcessDefineHuffmanTablesMarker(remaining); - } - - break; - case JpegConstants.Markers.DQT: - if (configOnly) - { - this.Skip(remaining); - } - else this.ProcessDqt(remaining); - break; - case JpegConstants.Markers.SOS: - if (configOnly) - { - return; - } - - this.ProcessStartOfScan(remaining); - break; - case JpegConstants.Markers.DRI: - if (configOnly) - { - this.Skip(remaining); - } - else - { - this.ProcessDefineRestartIntervalMarker(remaining); - } - - break; - case JpegConstants.Markers.APP0: - this.ProcessApplicationHeader(remaining); - break; - case JpegConstants.Markers.APP1: - this.ProcessApp1Marker(remaining, image); - break; - case JpegConstants.Markers.APP14: - this.ProcessApp14Marker(remaining); - break; - default: - if ((JpegConstants.Markers.APP0 <= marker && marker <= JpegConstants.Markers.APP15) || marker == JpegConstants.Markers.COM) - { - this.Skip(remaining); - } - else if (marker < JpegConstants.Markers.SOF0) - { - // See Table B.1 "Marker code assignments". - throw new ImageFormatException("Unknown marker"); - } - else - { - throw new ImageFormatException("Unknown marker"); - } - - break; - } - } - - if (this.grayImage != null) - { - this.ConvertFromGrayScale(this.imageWidth, this.imageHeight, image); - } - else if (this.ycbcrImage != null) - { - if (this.componentCount == 4) - { - this.ConvertFromCmyk(this.imageWidth, this.imageHeight, image); - return; - } - - if (this.componentCount == 3) - { - if (this.IsRGB()) - { - this.ConvertFromRGB(this.imageWidth, this.imageHeight, image); - return; - } - - this.ConvertFromYCbCr(this.imageWidth, this.imageHeight, image); - return; - } - - throw new ImageFormatException("JpegDecoder only supports RGB, CMYK and Grayscale color spaces."); - } - else - { - throw new ImageFormatException("Missing SOS marker."); - } - } - - /// - /// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at - /// least n. For best performance (avoiding function calls inside hot loops), - /// the caller is the one responsible for first checking that bits.UnreadBits < n. - /// - /// The number of bits to ensure. - private void EnsureNBits(int n) - { - while (true) - { - byte c = this.ReadByteStuffedByte(); - this.bits.Accumulator = (this.bits.Accumulator << 8) | c; - this.bits.UnreadBits += 8; - if (this.bits.Mask == 0) - { - this.bits.Mask = 1 << 7; - } - else - { - this.bits.Mask <<= 8; - } - - if (this.bits.UnreadBits >= n) - { - break; - } - } - } - - /// - /// The composition of RECEIVE and EXTEND, specified in section F.2.2.1. - /// - /// The byte - /// The - private int ReceiveExtend(byte t) - { - if (this.bits.UnreadBits < t) - { - this.EnsureNBits(t); - } - - this.bits.UnreadBits -= t; - this.bits.Mask >>= t; - int s = 1 << t; - int x = (int)((this.bits.Accumulator >> this.bits.UnreadBits) & (s - 1)); - - if (x < (s >> 1)) - { - x += ((-1) << t) + 1; - } - - return x; - } - - /// - /// Processes a Define Huffman Table marker, and initializes a huffman - /// struct from its contents. Specified in section B.2.4.2. - /// - /// The remaining bytes in the segment block. - private void ProcessDefineHuffmanTablesMarker(int remaining) - { - while (remaining > 0) - { - if (remaining < 17) - { - throw new ImageFormatException("DHT has wrong length"); - } - - this.ReadFull(this.temp, 0, 17); - - int tc = this.temp[0] >> 4; - if (tc > MaxTc) - { - throw new ImageFormatException("Bad Tc value"); - } - - int th = this.temp[0] & 0x0f; - if (th > MaxTh || (!this.isProgressive && (th > 1))) - { - throw new ImageFormatException("Bad Th value"); - } - - ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc* ThRowSize + th], ref remaining); - } - } - - private void ProcessDefineHuffmanTablesMarkerLoop(ref Huffman huffman, ref int remaining) - { - - // Read nCodes and huffman.Valuess (and derive h.Length). - // nCodes[i] is the number of codes with code length i. - // h.Length is the total number of codes. - huffman.Length = 0; - - int[] ncodes = new int[MaxCodeLength]; - for (int i = 0; i < ncodes.Length; i++) - { - ncodes[i] = this.temp[i + 1]; - huffman.Length += ncodes[i]; - } - - if (huffman.Length == 0) - { - throw new ImageFormatException("Huffman table has zero length"); - } - - if (huffman.Length > MaxNCodes) - { - throw new ImageFormatException("Huffman table has excessive length"); - } - - remaining -= huffman.Length + 17; - if (remaining < 0) - { - throw new ImageFormatException("DHT has wrong length"); - } - - this.ReadFull(huffman.Values, 0, huffman.Length); - - // Derive the look-up table. - for (int i = 0; i < huffman.Lut.Length; i++) - { - huffman.Lut[i] = 0; - } - - uint x = 0, code = 0; - - for (int i = 0; i < LutSize; i++) - { - code <<= 1; - - for (int j = 0; j < ncodes[i]; j++) - { - // The codeLength is 1+i, so shift code by 8-(1+i) to - // calculate the high bits for every 8-bit sequence - // whose codeLength's high bits matches code. - // The high 8 bits of lutValue are the encoded value. - // The low 8 bits are 1 plus the codeLength. - byte base2 = (byte) (code << (7 - i)); - ushort lutValue = (ushort) ((huffman.Values[x] << 8) | (2 + i)); - - for (int k = 0; k < 1 << (7 - i); k++) - { - huffman.Lut[base2 | k] = lutValue; - } - - code++; - x++; - } - } - - // Derive minCodes, maxCodes, and indices. - int c = 0, index = 0; - for (int i = 0; i < ncodes.Length; i++) - { - int nc = ncodes[i]; - if (nc == 0) - { - huffman.MinCodes[i] = -1; - huffman.MaxCodes[i] = -1; - huffman.Indices[i] = -1; - } - else - { - huffman.MinCodes[i] = c; - huffman.MaxCodes[i] = c + nc - 1; - huffman.Indices[i] = index; - c += nc; - index += nc; - } - - c <<= 1; - } - } - - /// - /// Returns the next Huffman-coded value from the bit-stream, decoded according to the given value. - /// - /// The huffman value - /// The - private byte DecodeHuffman(ref Huffman huffman) - { - if (huffman.Length == 0) - { - throw new ImageFormatException("Uninitialized Huffman table"); - } - - if (this.bits.UnreadBits < 8) - { - try - { - this.EnsureNBits(8); - - ushort v = huffman.Lut[(this.bits.Accumulator >> (this.bits.UnreadBits - LutSize)) & 0xff]; - - if (v != 0) - { - byte n = (byte)((v & 0xff) - 1); - this.bits.UnreadBits -= n; - this.bits.Mask >>= n; - return (byte)(v >> 8); - } - } - catch (MissingFF00Exception) - { - if (this.bytes.UnreadableBytes != 0) - { - this.UnreadByteStuffedByte(); - } - } - catch (ShortHuffmanDataException) - { - if (this.bytes.UnreadableBytes != 0) - { - this.UnreadByteStuffedByte(); - } - } - } - - int code = 0; - for (int i = 0; i < MaxCodeLength; i++) - { - if (this.bits.UnreadBits == 0) - { - this.EnsureNBits(1); - } - - if ((this.bits.Accumulator & this.bits.Mask) != 0) - { - code |= 1; - } - - this.bits.UnreadBits--; - this.bits.Mask >>= 1; - - if (code <= huffman.MaxCodes[i]) - { - return huffman.Values[huffman.Indices[i] + code - huffman.MinCodes[i]]; - } - - code <<= 1; - } - - throw new ImageFormatException("Bad Huffman code"); - } - - /// - /// Decodes a single bit - /// - /// The - private bool DecodeBit() - { - if (this.bits.UnreadBits == 0) - { - this.EnsureNBits(1); - } - - bool ret = (this.bits.Accumulator & this.bits.Mask) != 0; - this.bits.UnreadBits--; - this.bits.Mask >>= 1; - return ret; - } - - /// - /// Decodes the given number of bits - /// - /// The number of bits to decode. - /// The - private uint DecodeBits(int count) - { - if (this.bits.UnreadBits < count) - { - this.EnsureNBits(count); - } - - uint ret = this.bits.Accumulator >> (this.bits.UnreadBits - count); - ret = (uint)(ret & ((1 << count) - 1)); - this.bits.UnreadBits -= count; - this.bits.Mask >>= count; - return ret; - } - - /// - /// Fills up the bytes buffer from the underlying stream. - /// It should only be called when there are no unread bytes in bytes. - /// - private void Fill() - { - if (this.bytes.I != this.bytes.J) - { - throw new ImageFormatException("Fill called when unread bytes exist."); - } - - // Move the last 2 bytes to the start of the buffer, in case we need - // to call UnreadByteStuffedByte. - if (this.bytes.J > 2) - { - this.bytes.Buffer[0] = this.bytes.Buffer[this.bytes.J - 2]; - this.bytes.Buffer[1] = this.bytes.Buffer[this.bytes.J - 1]; - this.bytes.I = 2; - this.bytes.J = 2; - } - - // Fill in the rest of the buffer. - int n = this.inputStream.Read(this.bytes.Buffer, this.bytes.J, this.bytes.Buffer.Length - this.bytes.J); - if (n == 0) - { - throw new EOFException(); - } - - this.bytes.J += n; - } - - /// - /// Undoes the most recent ReadByteStuffedByte call, - /// giving a byte of data back from bits to bytes. The Huffman look-up table - /// requires at least 8 bits for look-up, which means that Huffman decoding can - /// sometimes overshoot and read one or two too many bytes. Two-byte overshoot - /// can happen when expecting to read a 0xff 0x00 byte-stuffed byte. - /// - private void UnreadByteStuffedByte() - { - this.bytes.I -= this.bytes.UnreadableBytes; - this.bytes.UnreadableBytes = 0; - if (this.bits.UnreadBits >= 8) - { - this.bits.Accumulator >>= 8; - this.bits.UnreadBits -= 8; - this.bits.Mask >>= 8; - } - } - - /// - /// Returns the next byte, whether buffered or not buffered. It does not care about byte stuffing. - /// - /// The - private byte ReadByte() - { - while (this.bytes.I == this.bytes.J) - { - this.Fill(); - } - - byte x = this.bytes.Buffer[this.bytes.I]; - this.bytes.I++; - this.bytes.UnreadableBytes = 0; - return x; - } - - /// - /// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data. - /// - /// The - private byte ReadByteStuffedByte() - { - byte x; - - // Take the fast path if bytes.buf contains at least two bytes. - if (this.bytes.I + 2 <= this.bytes.J) - { - x = this.bytes.Buffer[this.bytes.I]; - this.bytes.I++; - this.bytes.UnreadableBytes = 1; - if (x != JpegConstants.Markers.XFF) - { - return x; - } - - if (this.bytes.Buffer[this.bytes.I] != 0x00) - { - throw new MissingFF00Exception(); - } - - this.bytes.I++; - this.bytes.UnreadableBytes = 2; - return JpegConstants.Markers.XFF; - } - - this.bytes.UnreadableBytes = 0; - - x = this.ReadByte(); - this.bytes.UnreadableBytes = 1; - if (x != JpegConstants.Markers.XFF) - { - return x; - } - - x = this.ReadByte(); - this.bytes.UnreadableBytes = 2; - if (x != 0x00) - { - throw new MissingFF00Exception(); - } - - return JpegConstants.Markers.XFF; - } - - /// - /// Reads exactly length bytes into data. It does not care about byte stuffing. - /// - /// The data to write to. - /// The offset in the source buffer - /// The number of bytes to read - private void ReadFull(byte[] data, int offset, int length) - { - // Unread the overshot bytes, if any. - if (this.bytes.UnreadableBytes != 0) - { - if (this.bits.UnreadBits >= 8) - { - this.UnreadByteStuffedByte(); - } - - this.bytes.UnreadableBytes = 0; - } - - while (length > 0) - { - if (this.bytes.J - this.bytes.I >= length) - { - Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, length); - this.bytes.I += length; - length -= length; - } - else - { - Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, this.bytes.J - this.bytes.I); - offset += this.bytes.J - this.bytes.I; - length -= this.bytes.J - this.bytes.I; - this.bytes.I += this.bytes.J - this.bytes.I; - - this.Fill(); - } - } - } - - /// - /// Skips the next n bytes. - /// - /// The number of bytes to ignore. - private void Skip(int count) - { - // Unread the overshot bytes, if any. - if (this.bytes.UnreadableBytes != 0) - { - if (this.bits.UnreadBits >= 8) - { - this.UnreadByteStuffedByte(); - } - - this.bytes.UnreadableBytes = 0; - } - - while (true) - { - int m = this.bytes.J - this.bytes.I; - if (m > count) - { - m = count; - } - - this.bytes.I += m; - count -= m; - if (count == 0) - { - break; - } - - this.Fill(); - } - } - - /// - /// Processes the Start of Frame marker. Specified in section B.2.2. - /// - /// The remaining bytes in the segment block. - private void ProcessStartOfFrameMarker(int remaining) - { - if (this.componentCount != 0) - { - throw new ImageFormatException("Multiple SOF markers"); - } - - switch (remaining) - { - case 6 + (3 * 1): // Grayscale image. - this.componentCount = 1; - break; - case 6 + (3 * 3): // YCbCr or RGB image. - this.componentCount = 3; - break; - case 6 + (3 * 4): // YCbCrK or CMYK image. - this.componentCount = 4; - break; - default: - throw new ImageFormatException("Incorrect number of components"); - } - - this.ReadFull(this.temp, 0, remaining); - - // We only support 8-bit precision. - if (this.temp[0] != 8) - { - throw new ImageFormatException("Only 8-Bit precision supported."); - } - - this.imageHeight = (this.temp[1] << 8) + this.temp[2]; - this.imageWidth = (this.temp[3] << 8) + this.temp[4]; - if (this.temp[5] != this.componentCount) - { - throw new ImageFormatException("SOF has wrong length"); - } - - for (int i = 0; i < this.componentCount; i++) - { - this.componentArray[i].Identifier = this.temp[6 + (3 * i)]; - - // Section B.2.2 states that "the value of C_i shall be different from - // the values of C_1 through C_(i-1)". - for (int j = 0; j < i; j++) - { - if (this.componentArray[i].Identifier == this.componentArray[j].Identifier) - { - throw new ImageFormatException("Repeated component identifier"); - } - } - - this.componentArray[i].Selector = this.temp[8 + (3 * i)]; - if (this.componentArray[i].Selector > MaxTq) - { - throw new ImageFormatException("Bad Tq value"); - } - - byte hv = this.temp[7 + (3 * i)]; - int h = hv >> 4; - int v = hv & 0x0f; - if (h < 1 || h > 4 || v < 1 || v > 4) - { - throw new ImageFormatException("Unsupported Luma/chroma subsampling ratio"); - } - - if (h == 3 || v == 3) - { - throw new ImageFormatException("Lnsupported subsampling ratio"); - } - - switch (this.componentCount) - { - case 1: - - // If a JPEG image has only one component, section A.2 says "this data - // is non-interleaved by definition" and section A.2.2 says "[in this - // case...] the order of data units within a scan shall be left-to-right - // and top-to-bottom... regardless of the values of H_1 and V_1". Section - // 4.8.2 also says "[for non-interleaved data], the MCU is defined to be - // one data unit". Similarly, section A.1.1 explains that it is the ratio - // of H_i to max_j(H_j) that matters, and similarly for V. For grayscale - // images, H_1 is the maximum H_j for all components j, so that ratio is - // always 1. The component's (h, v) is effectively always (1, 1): even if - // the nominal (h, v) is (2, 1), a 20x5 image is encoded in three 8x8 - // MCUs, not two 16x8 MCUs. - h = 1; - v = 1; - break; - - case 3: - - // For YCbCr images, we only support 4:4:4, 4:4:0, 4:2:2, 4:2:0, - // 4:1:1 or 4:1:0 chroma subsampling ratios. This implies that the - // (h, v) values for the Y component are either (1, 1), (1, 2), - // (2, 1), (2, 2), (4, 1) or (4, 2), and the Y component's values - // must be a multiple of the Cb and Cr component's values. We also - // assume that the two chroma components have the same subsampling - // ratio. - switch (i) - { - case 0: - { - // Y. - // We have already verified, above, that h and v are both - // either 1, 2 or 4, so invalid (h, v) combinations are those - // with v == 4. - if (v == 4) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - } - - case 1: - { - // Cb. - if (this.componentArray[0].HorizontalFactor % h != 0 || this.componentArray[0].VerticalFactor % v != 0) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - } - - case 2: - { - // Cr. - if (this.componentArray[1].HorizontalFactor != h || this.componentArray[1].VerticalFactor != v) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - } - } - - break; - - case 4: - - // For 4-component images (either CMYK or YCbCrK), we only support two - // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22]. - // Theoretically, 4-component JPEG images could mix and match hv values - // but in practice, those two combinations are the only ones in use, - // and it simplifies the applyBlack code below if we can assume that: - // - for CMYK, the C and K channels have full samples, and if the M - // and Y channels subsample, they subsample both horizontally and - // vertically. - // - for YCbCrK, the Y and K channels have full samples. - switch (i) - { - case 0: - if (hv != 0x11 && hv != 0x22) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - case 1: - case 2: - if (hv != 0x11) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - case 3: - if (this.componentArray[0].HorizontalFactor != h || this.componentArray[0].VerticalFactor != v) - { - throw new ImageFormatException("Unsupported subsampling ratio"); - } - - break; - } - - break; - } - - this.componentArray[i].HorizontalFactor = h; - this.componentArray[i].VerticalFactor = v; - } - } - - /// - /// Processes the Define Quantization Marker and tables. Specified in section B.2.4.1. - /// - /// The remaining bytes in the segment block. - /// - /// Thrown if the tables do not match the header - /// - private void ProcessDqt(int remaining) - { - while (remaining > 0) - { - bool done = false; - - remaining--; - byte x = this.ReadByte(); - byte tq = (byte)(x & 0x0f); - if (tq > MaxTq) - { - throw new ImageFormatException("Bad Tq value"); - } - - switch (x >> 4) - { - case 0: - if (remaining < Block.BlockSize) - { - done = true; - break; - } - - remaining -= Block.BlockSize; - this.ReadFull(this.temp, 0, Block.BlockSize); - - for (int i = 0; i < Block.BlockSize; i++) - { - this.quantizationTables[tq][i] = this.temp[i]; - } - - break; - case 1: - if (remaining < 2 * Block.BlockSize) - { - done = true; - break; - } - - remaining -= 2 * Block.BlockSize; - this.ReadFull(this.temp, 0, 2 * Block.BlockSize); - - for (int i = 0; i < Block.BlockSize; i++) - { - this.quantizationTables[tq][i] = (this.temp[2 * i] << 8) | this.temp[(2 * i) + 1]; - } - - break; - default: - throw new ImageFormatException("Bad Pq value"); - } - - if (done) - { - break; - } - } - - if (remaining != 0) - { - throw new ImageFormatException("DQT has wrong length"); - } - } - - /// - /// Processes the DRI (Define Restart Interval Marker) Which specifies the interval between RSTn markers, in macroblocks - /// - /// The remaining bytes in the segment block. - private void ProcessDefineRestartIntervalMarker(int remaining) - { - if (remaining != 2) - { - throw new ImageFormatException("DRI has wrong length"); - } - - this.ReadFull(this.temp, 0, 2); - this.restartInterval = ((int)this.temp[0] << 8) + (int)this.temp[1]; - } - - /// - /// Processes the application header containing the JFIF identifier plus extra data. - /// - /// The remaining bytes in the segment block. - private void ProcessApplicationHeader(int remaining) - { - if (remaining < 5) - { - this.Skip(remaining); - return; - } - - this.ReadFull(this.temp, 0, 13); - remaining -= 13; - - // TODO: We should be using constants for this. - this.isJfif = this.temp[0] == 'J' && - this.temp[1] == 'F' && - this.temp[2] == 'I' && - this.temp[3] == 'F' && - this.temp[4] == '\x00'; - - if (this.isJfif) - { - this.horizontalResolution = (short)(this.temp[9] + (this.temp[10] << 8)); - this.verticalResolution = (short)(this.temp[11] + (this.temp[12] << 8)); - } - - if (remaining > 0) - { - this.Skip(remaining); - } - } - - /// - /// Processes the App1 marker retrieving any stored metadata - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The remaining bytes in the segment block. - /// The image. - private void ProcessApp1Marker(int remaining, Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (remaining < 6) - { - this.Skip(remaining); - return; - } - - byte[] profile = new byte[remaining]; - this.ReadFull(profile, 0, remaining); - - if (profile[0] == 'E' && - profile[1] == 'x' && - profile[2] == 'i' && - profile[3] == 'f' && - profile[4] == '\0' && - profile[5] == '\0') - { - image.ExifProfile = new ExifProfile(profile); - } - } - - /// - /// Processes the "Adobe" APP14 segment stores image encoding information for DCT filters. - /// This segment may be copied or deleted as a block using the Extra "Adobe" tag, but note that it is not - /// deleted by default when deleting all metadata because it may affect the appearance of the image. - /// - /// The remaining number of bytes in the stream. - private void ProcessApp14Marker(int remaining) - { - if (remaining < 12) - { - this.Skip(remaining); - return; - } - - this.ReadFull(this.temp, 0, 12); - remaining -= 12; - - if (this.temp[0] == 'A' && - this.temp[1] == 'd' && - this.temp[2] == 'o' && - this.temp[3] == 'b' && - this.temp[4] == 'e') - { - this.adobeTransformValid = true; - this.adobeTransform = this.temp[11]; - } - - if (remaining > 0) - { - this.Skip(remaining); - } - } - - /// - /// Converts the image from the original CMYK image pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image width. - /// The image height. - /// The image. - private void ConvertFromCmyk(int width, int height, Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (!this.adobeTransformValid) - { - throw new ImageFormatException("Unknown color model: 4-component JPEG doesn't have Adobe APP14 metadata"); - } - - // If the 4-component JPEG image isn't explicitly marked as "Unknown (RGB - // or CMYK)" as per http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe - if (this.adobeTransform != JpegConstants.Adobe.ColorTransformUnknown) - { - int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor; - - image.InitPixels(width, height); - - using (PixelAccessor pixels = image.Lock()) - { - // Convert the YCbCr part of the YCbCrK to RGB, invert the RGB to get - // CMY, and patch in the original K. The RGB to CMY inversion cancels - // out the 'Adobe inversion' described in the applyBlack doc comment - // above, so in practice, only the fourth channel (black) is inverted. - Parallel.For( - 0, - height, - y => - { - int yo = this.ycbcrImage.GetRowYOffset(y); - int co = this.ycbcrImage.GetRowCOffset(y); - - for (int x = 0; x < width; x++) - { - byte yy = this.ycbcrImage.YChannel[yo + x]; - byte cb = this.ycbcrImage.CbChannel[co + (x / scale)]; - byte cr = this.ycbcrImage.CrChannel[co + (x / scale)]; - - TColor packed = default(TColor); - this.PackCmyk(ref packed, yy, cb, cr, x, y); - pixels[x, y] = packed; - } - }); - } - - this.AssignResolution(image); - } - } - - /// - /// Converts the image from the original grayscale image pixels. - /// - /// The pixel format. - /// The packed format. long, float. - /// The image width. - /// The image height. - /// The image. - private void ConvertFromGrayScale(int width, int height, Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - image.InitPixels(width, height); - - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - height, - Bootstrapper.Instance.ParallelOptions, - y => - { - int yoff = this.grayImage.GetRowOffset(y); - for (int x = 0; x < width; x++) - { - byte rgb = this.grayImage.Pixels[yoff + x]; - - TColor packed = default(TColor); - packed.PackFromBytes(rgb, rgb, rgb, 255); - pixels[x, y] = packed; - } - }); - } - - this.AssignResolution(image); - } - - /// - /// Converts the image from the original YCbCr image pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image width. - /// The image height. - /// The image. - private void ConvertFromYCbCr(int width, int height, Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor; - image.InitPixels(width, height); - - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - height, - Bootstrapper.Instance.ParallelOptions, - y => - { - int yo = this.ycbcrImage.GetRowYOffset(y); - int co = this.ycbcrImage.GetRowCOffset(y); - - for (int x = 0; x < width; x++) - { - byte yy = this.ycbcrImage.YChannel[yo + x]; - byte cb = this.ycbcrImage.CbChannel[co + (x / scale)]; - byte cr = this.ycbcrImage.CrChannel[co + (x / scale)]; - - TColor packed = default(TColor); - PackYcbCr(ref packed, yy, cb, cr); - pixels[x, y] = packed; - } - }); - } - - this.AssignResolution(image); - } - - /// - /// Converts the image from the original RBG image pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image width. - /// The height. - /// The image. - private void ConvertFromRGB(int width, int height, Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor; - image.InitPixels(width, height); - - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - height, - Bootstrapper.Instance.ParallelOptions, - y => - { - int yo = this.ycbcrImage.GetRowYOffset(y); - int co = this.ycbcrImage.GetRowCOffset(y); - - for (int x = 0; x < width; x++) - { - byte red = this.ycbcrImage.YChannel[yo + x]; - byte green = this.ycbcrImage.CbChannel[co + (x / scale)]; - byte blue = this.ycbcrImage.CrChannel[co + (x / scale)]; - - TColor packed = default(TColor); - packed.PackFromBytes(red, green, blue, 255); - pixels[x, y] = packed; - } - }); - } - - this.AssignResolution(image); - } - - /// - /// Assigns the horizontal and vertical resolution to the image if it has a JFIF header. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to assign the resolution to. - private void AssignResolution(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (this.isJfif && this.horizontalResolution > 0 && this.verticalResolution > 0) - { - image.HorizontalResolution = this.horizontalResolution; - image.VerticalResolution = this.verticalResolution; - } - } - - private Block scanWorkerBlock = Block.Create(); - - /// - /// Processes the SOS (Start of scan marker). - /// - /// - /// TODO: This also needs some significant refactoring to follow a more OO format. - /// - /// The remaining bytes in the segment block. - /// - /// Missing SOF Marker - /// SOS has wrong length - /// - private void ProcessStartOfScan(int remaining) - { - if (this.componentCount == 0) - { - throw new ImageFormatException("Missing SOF marker"); - } - - if (remaining < 6 || 4 + (2 * this.componentCount) < remaining || remaining % 2 != 0) - { - throw new ImageFormatException("SOS has wrong length"); - } - - this.ReadFull(this.temp, 0, remaining); - byte scanComponentCount = this.temp[0]; - - int scanComponentCountX2 = 2 * scanComponentCount; - if (remaining != 4 + scanComponentCountX2) - { - throw new ImageFormatException("SOS length inconsistent with number of components"); - } - - Scan[] scan = new Scan[MaxComponents]; - int totalHv = 0; - - for (int i = 0; i < scanComponentCount; i++) - { - ProcessScanImpl(i, ref scan[i], scan, ref totalHv); - } - - // Section B.2.3 states that if there is more than one component then the - // total H*V values in a scan must be <= 10. - if (this.componentCount > 1 && totalHv > 10) - { - throw new ImageFormatException("Total sampling factors too large."); - } - - // zigStart and zigEnd are the spectral selection bounds. - // ah and al are the successive approximation high and low values. - // The spec calls these values Ss, Se, Ah and Al. - // For progressive JPEGs, these are the two more-or-less independent - // aspects of progression. Spectral selection progression is when not - // all of a block's 64 DCT coefficients are transmitted in one pass. - // For example, three passes could transmit coefficient 0 (the DC - // component), coefficients 1-5, and coefficients 6-63, in zig-zag - // order. Successive approximation is when not all of the bits of a - // band of coefficients are transmitted in one pass. For example, - // three passes could transmit the 6 most significant bits, followed - // by the second-least significant bit, followed by the least - // significant bit. - // For baseline JPEGs, these parameters are hard-coded to 0/63/0/0. - int zigStart = 0; - int zigEnd = Block.BlockSize - 1; - int ah = 0; - int al = 0; - - if (this.isProgressive) - { - zigStart = this.temp[1 + scanComponentCountX2]; - zigEnd = this.temp[2 + scanComponentCountX2]; - ah = this.temp[3 + scanComponentCountX2] >> 4; - al = this.temp[3 + scanComponentCountX2] & 0x0f; - - if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || Block.BlockSize <= zigEnd) - { - throw new ImageFormatException("Bad spectral selection bounds"); - } - - if (zigStart != 0 && scanComponentCount != 1) - { - throw new ImageFormatException("Progressive AC coefficients for more than one component"); - } - - if (ah != 0 && ah != al + 1) - { - throw new ImageFormatException("Bad successive approximation values"); - } - } - - // mxx and myy are the number of MCUs (Minimum Coded Units) in the image. - int h0 = this.componentArray[0].HorizontalFactor; - int v0 = this.componentArray[0].VerticalFactor; - int mxx = (this.imageWidth + (8 * h0) - 1) / (8 * h0); - int myy = (this.imageHeight + (8 * v0) - 1) / (8 * v0); - - if (this.grayImage == null && this.ycbcrImage == null) - { - this.MakeImage(mxx, myy); - } - - if (this.isProgressive) - { - for (int i = 0; i < scanComponentCount; i++) - { - int compIndex = scan[i].Index; - if (this.progCoeffs[compIndex] == null) - { - this.progCoeffs[compIndex] = Block.CreateArray(mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor); - - for (int j = 0; j < this.progCoeffs[compIndex].Length; j++) - { - this.progCoeffs[compIndex][j].Init(); - } - } - } - } - - this.bits = new Bits(); - - int mcu = 0; - byte expectedRst = JpegConstants.Markers.RST0; - - // b is the decoded coefficients block, in natural (not zig-zag) order. - //Block b; - int[] dc = new int[MaxComponents]; - - // bx and by are the location of the current block, in units of 8x8 - // blocks: the third block in the first row has (bx, by) = (2, 0). - int bx, by, blockCount = 0; - - for (int my = 0; my < myy; my++) - { - for (int mx = 0; mx < mxx; mx++) - { - for (int i = 0; i < scanComponentCount; i++) - { - int compIndex = scan[i].Index; - int hi = this.componentArray[compIndex].HorizontalFactor; - int vi = this.componentArray[compIndex].VerticalFactor; - - - for (int j = 0; j < hi * vi; j++) - { - // The blocks are traversed one MCU at a time. For 4:2:0 chroma - // subsampling, there are four Y 8x8 blocks in every 16x16 MCU. - // For a baseline 32x16 pixel image, the Y blocks visiting order is: - // 0 1 4 5 - // 2 3 6 7 - // For progressive images, the interleaved scans (those with component count > 1) - // are traversed as above, but non-interleaved scans are traversed left - // to right, top to bottom: - // 0 1 2 3 - // 4 5 6 7 - // Only DC scans (zigStart == 0) can be interleave AC scans must have - // only one component. - // To further complicate matters, for non-interleaved scans, there is no - // data for any blocks that are inside the image at the MCU level but - // outside the image at the pixel level. For example, a 24x16 pixel 4:2:0 - // progressive image consists of two 16x16 MCUs. The interleaved scans - // will process 8 Y blocks: - // 0 1 4 5 - // 2 3 6 7 - // The non-interleaved scans will process only 6 Y blocks: - // 0 1 2 - // 3 4 5 - if (scanComponentCount != 1) - { - bx = (hi * mx) + (j % hi); - by = (vi * my) + (j / hi); - } - else - { - int q = mxx * hi; - bx = blockCount % q; - by = blockCount / q; - blockCount++; - if (bx * 8 >= this.imageWidth || by * 8 >= this.imageHeight) - { - continue; - } - } - - var qtIndex = this.componentArray[compIndex].Selector; - - if (this.isProgressive) // Load the previous partially decoded coefficients, if applicable. - { - blockIndex = ((@by * mxx) * hi) + bx; - ProcessBlockImpl(ah, - ref this.progCoeffs[compIndex][blockIndex], - scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, bx, - ref this.quantizationTables[qtIndex] - ); - } - else - { - //var b = Block.Create(); - scanWorkerBlock.Clear(); - - ProcessBlockImpl(ah, ref scanWorkerBlock, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, - bx, ref this.quantizationTables[qtIndex] - ); - - //b.Dispose(); - } - } - - // for j - } - - // for i - mcu++; - - if (this.restartInterval > 0 && mcu % this.restartInterval == 0 && mcu < mxx * myy) - { - // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input, - // but this one assumes well-formed input, and hence the restart marker follows immediately. - this.ReadFull(this.temp, 0, 2); - if (this.temp[0] != 0xff || this.temp[1] != expectedRst) - { - throw new ImageFormatException("Bad RST marker"); - } - - expectedRst++; - if (expectedRst == JpegConstants.Markers.RST7 + 1) - { - expectedRst = JpegConstants.Markers.RST0; - } - - // Reset the Huffman decoder. - this.bits = new Bits(); - - // Reset the DC components, as per section F.2.1.3.1. - dc = new int[MaxComponents]; - - // Reset the progressive decoder state, as per section G.1.2.2. - this.eobRun = 0; - } - } - - // for mx - } - - // for my - } - - private void ProcessBlockImpl(int ah, ref Block b, Scan[] scan, int i, int zigStart, int zigEnd, int al, - int[] dc, int compIndex, int @by, int mxx, int hi, int bx, ref Block qt) - { - if (ah != 0) - { - this.Refine(ref b, ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector], zigStart, zigEnd, 1 << al); - } - else - { - int zig = zigStart; - if (zig == 0) - { - zig++; - - // Decode the DC coefficient, as specified in section F.2.2.1. - byte value = this.DecodeHuffman(ref this.huffmanTrees[DcTable * ThRowSize + scan[i].DcTableSelector]); - if (value > 16) - { - throw new ImageFormatException("Excessive DC component"); - } - - int deltaDC = this.ReceiveExtend(value); - dc[compIndex] += deltaDC; - b[0] = dc[compIndex] << al; - } - - if (zig <= zigEnd && this.eobRun > 0) - { - this.eobRun--; - } - else - { - // Decode the AC coefficients, as specified in section F.2.2.2. - //Huffman huffv = ; - for (; zig <= zigEnd; zig++) - { - byte value = this.DecodeHuffman(ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector]); - byte val0 = (byte) (value >> 4); - byte val1 = (byte) (value & 0x0f); - if (val1 != 0) - { - zig += val0; - if (zig > zigEnd) - { - break; - } - - int ac = this.ReceiveExtend(val1); - b[Unzig[zig]] = ac << al; - } - else - { - if (val0 != 0x0f) - { - this.eobRun = (ushort) (1 << val0); - if (val0 != 0) - { - this.eobRun |= (ushort) this.DecodeBits(val0); - } - - this.eobRun--; - break; - } - - zig += 0x0f; - } - } - } - } - - if (this.isProgressive) - { - if (zigEnd != Block.BlockSize - 1 || al != 0) - { - // We haven't completely decoded this 8x8 block. Save the coefficients. - - this.progCoeffs[compIndex][((@by*mxx)*hi) + bx] = b.Clone(); - - // At this point, we could execute the rest of the loop body to dequantize and - // perform the inverse DCT, to save early stages of a progressive image to the - // *image.YCbCr buffers (the whole point of progressive encoding), but in Go, - // the jpeg.Decode function does not return until the entire image is decoded, - // so we "continue" here to avoid wasted computation. - return; - } - } - - // Dequantize, perform the inverse DCT and store the block to the image. - for (int zig = 0; zig < Block.BlockSize; zig++) - { - b[Unzig[zig]] *= qt[zig]; - } - - //IDCT.Transform(ref b); - //FloatIDCT.Transform(ref b); - MagicDCT.IDCT(ref b); - - byte[] dst; - int offset; - int stride; - - if (this.componentCount == 1) - { - dst = this.grayImage.Pixels; - stride = this.grayImage.Stride; - offset = this.grayImage.Offset + (8*((@by*this.grayImage.Stride) + bx)); - } - else - { - switch (compIndex) - { - case 0: - dst = this.ycbcrImage.YChannel; - stride = this.ycbcrImage.YStride; - offset = this.ycbcrImage.YOffset + (8*((@by*this.ycbcrImage.YStride) + bx)); - break; - - case 1: - dst = this.ycbcrImage.CbChannel; - stride = this.ycbcrImage.CStride; - offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); - break; - - case 2: - dst = this.ycbcrImage.CrChannel; - stride = this.ycbcrImage.CStride; - offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); - break; - - case 3: - - dst = this.blackPixels; - stride = this.blackStride; - offset = 8*((@by*this.blackStride) + bx); - break; - - default: - throw new ImageFormatException("Too many components"); - } - } - - // Level shift by +128, clip to [0, 255], and write to dst. - for (int y = 0; y < 8; y++) - { - int y8 = y*8; - int yStride = y*stride; - - for (int x = 0; x < 8; x++) - { - int c = b[y8 + x]; - if (c < -128) - { - c = 0; - } - else if (c > 127) - { - c = 255; - } - else - { - c += 128; - } - - dst[yStride + x + offset] = (byte) c; - } - } - } - - private void ProcessScanImpl(int i, ref Scan currentScan, Scan[] scan, ref int totalHv) - { - // Component selector. - int cs = this.temp[1 + (2 * i)]; - int compIndex = -1; - for (int j = 0; j < this.componentCount; j++) - { - //Component compv = ; - if (cs == this.componentArray[j].Identifier) - { - compIndex = j; - } - } - - if (compIndex < 0) - { - throw new ImageFormatException("Unknown component selector"); - } - - currentScan.Index = (byte)compIndex; - - ProcessComponentImpl(i, ref currentScan, scan, ref totalHv, ref this.componentArray[compIndex]); - } - - private void ProcessComponentImpl(int i, ref Scan currentScan, Scan[] scan, ref int totalHv, ref Component currentComponent) - { - // Section B.2.3 states that "the value of Cs_j shall be different from - // the values of Cs_1 through Cs_(j-1)". Since we have previously - // verified that a frame's component identifiers (C_i values in section - // B.2.2) are unique, it suffices to check that the implicit indexes - // into comp are unique. - for (int j = 0; j < i; j++) - { - if (currentScan.Index == scan[j].Index) - { - throw new ImageFormatException("Repeated component selector"); - } - } - - - totalHv += currentComponent.HorizontalFactor*currentComponent.VerticalFactor; - - currentScan.DcTableSelector = (byte) (this.temp[2 + (2*i)] >> 4); - if (currentScan.DcTableSelector > MaxTh) - { - throw new ImageFormatException("Bad DC table selector value"); - } - - currentScan.AcTableSelector = (byte) (this.temp[2 + (2*i)] & 0x0f); - if (currentScan.AcTableSelector > MaxTh) - { - throw new ImageFormatException("Bad AC table selector value"); - } - } - - /// - /// Decodes a successive approximation refinement block, as specified in section G.1.2. - /// - /// The block of coefficients - /// The Huffman tree - /// The zig-zag start index - /// The zig-zag end index - /// The low transform offset - private void Refine(ref Block b, ref Huffman h, int zigStart, int zigEnd, int delta) - { - // Refining a DC component is trivial. - if (zigStart == 0) - { - if (zigEnd != 0) - { - throw new ImageFormatException("Invalid state for zig DC component"); - } - - bool bit = this.DecodeBit(); - if (bit) - { - b[0] |= delta; - } - - return; - } - - // Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3. - int zig = zigStart; - if (this.eobRun == 0) - { - for (; zig <= zigEnd; zig++) - { - bool done = false; - int z = 0; - byte val = this.DecodeHuffman(ref h); - int val0 = val >> 4; - int val1 = val & 0x0f; - - switch (val1) - { - case 0: - if (val0 != 0x0f) - { - this.eobRun = (ushort)(1 << val0); - if (val0 != 0) - { - this.eobRun |= (ushort)this.DecodeBits(val0); - } - - done = true; - } - - break; - case 1: - z = delta; - bool bit = this.DecodeBit(); - if (!bit) - { - z = -z; - } - - break; - default: - throw new ImageFormatException("Unexpected Huffman code"); - } - - if (done) - { - break; - } - - zig = this.RefineNonZeroes(b, zig, zigEnd, val0, delta); - if (zig > zigEnd) - { - throw new ImageFormatException($"Too many coefficients {zig} > {zigEnd}"); - } - - if (z != 0) - { - b[Unzig[zig]] = z; - } - } - } - - if (this.eobRun > 0) - { - this.eobRun--; - this.RefineNonZeroes(b, zig, zigEnd, -1, delta); - } - } - - /// - /// Refines non-zero entries of b in zig-zag order. - /// If >= 0, the first zero entries are skipped over. - /// - /// The block of coefficients - /// The zig-zag start index - /// The zig-zag end index - /// The non-zero entry - /// The low transform offset - /// The - private int RefineNonZeroes(Block b, int zig, int zigEnd, int nz, int delta) - { - for (; zig <= zigEnd; zig++) - { - int u = Unzig[zig]; - if (b[u] == 0) - { - if (nz == 0) - { - break; - } - - nz--; - continue; - } - - bool bit = this.DecodeBit(); - if (!bit) - { - continue; - } - - if (b[u] >= 0) - { - b[u] += delta; - } - else - { - b[u] -= delta; - } - } - - return zig; - } - - /// - /// Makes the image from the buffer. - /// - /// The horizontal MCU count - /// The vertical MCU count - private void MakeImage(int mxx, int myy) - { - if (this.componentCount == 1) - { - GrayImage gray = new GrayImage(8 * mxx, 8 * myy); - this.grayImage = gray.Subimage(0, 0, this.imageWidth, this.imageHeight); - } - else - { - int h0 = this.componentArray[0].HorizontalFactor; - int v0 = this.componentArray[0].VerticalFactor; - int horizontalRatio = h0 / this.componentArray[1].HorizontalFactor; - int verticalRatio = v0 / this.componentArray[1].VerticalFactor; - - YCbCrImage.YCbCrSubsampleRatio ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444; - switch ((horizontalRatio << 4) | verticalRatio) - { - case 0x11: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444; - break; - case 0x12: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440; - break; - case 0x21: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422; - break; - case 0x22: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio420; - break; - case 0x41: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio411; - break; - case 0x42: - ratio = YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio410; - break; - } - - YCbCrImage ycbcr = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio); - this.ycbcrImage = ycbcr.Subimage(0, 0, this.imageWidth, this.imageHeight); - - if (this.componentCount == 4) - { - int h3 = this.componentArray[3].HorizontalFactor; - int v3 = this.componentArray[3].VerticalFactor; - this.blackPixels = new byte[8 * h3 * mxx * 8 * v3 * myy]; - this.blackStride = 8 * h3 * mxx; - } - } - } - - /// - /// Returns a value indicating whether the image in an RGB image. - /// - /// - /// The . - /// - private bool IsRGB() - { - if (this.isJfif) - { - return false; - } - - if (this.adobeTransformValid && this.adobeTransform == JpegConstants.Adobe.ColorTransformUnknown) - { - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe - // says that 0 means Unknown (and in practice RGB) and 1 means YCbCr. - return true; - } - - return this.componentArray[0].Identifier == 'R' && this.componentArray[1].Identifier == 'G' && this.componentArray[2].Identifier == 'B'; - } - - /// - /// Optimized method to pack bytes to the image from the YCbCr color space. - /// This is faster than implicit casting as it avoids double packing. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The packed pixel. - /// The y luminance component. - /// The cb chroma component. - /// The cr chroma component. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void PackYcbCr(ref TColor packed, byte y, byte cb, byte cr) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int ccb = cb - 128; - int ccr = cr - 128; - - byte r = (byte)(y + (1.402F * ccr)).Clamp(0, 255); - byte g = (byte)(y - (0.34414F * ccb) - (0.71414F * ccr)).Clamp(0, 255); - byte b = (byte)(y + (1.772F * ccb)).Clamp(0, 255); - - packed.PackFromBytes(r, g, b, 255); - } - - /// - /// Optimized method to pack bytes to the image from the CMYK color space. - /// This is faster than implicit casting as it avoids double packing. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The packed pixel. - /// The y luminance component. - /// The cb chroma component. - /// The cr chroma component. - /// The x-position within the image. - /// The y-position within the image. - private void PackCmyk(ref TColor packed, byte y, byte cb, byte cr, int xx, int yy) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // TODO: We can speed this up further with Vector4 - int ccb = cb - 128; - int ccr = cr - 128; - - // First convert from YCbCr to CMY - float cyan = (y + (1.402F * ccr)).Clamp(0, 255) / 255F; - float magenta = (y - (0.34414F * ccb) - (0.71414F * ccr)).Clamp(0, 255) / 255F; - float yellow = (y + (1.772F * ccb)).Clamp(0, 255) / 255F; - - // Get keyline - float keyline = (255 - this.blackPixels[(yy * this.blackStride) + xx]) / 255F; - - // Convert back to RGB - byte r = (byte)(((1 - cyan) * (1 - keyline)).Clamp(0, 1) * 255); - byte g = (byte)(((1 - magenta) * (1 - keyline)).Clamp(0, 1) * 255); - byte b = (byte)(((1 - yellow) * (1 - keyline)).Clamp(0, 1) * 255); - - packed.PackFromBytes(r, g, b, 255); - } - - /// - /// Represents a component scan - /// - private struct Scan - { - /// - /// Gets or sets the component index. - /// - public byte Index { get; set; } - - /// - /// Gets or sets the DC table selector - /// - public byte DcTableSelector { get; set; } - - /// - /// Gets or sets the AC table selector - /// - public byte AcTableSelector { get; set; } - } - - /// - /// The missing ff00 exception. - /// - private class MissingFF00Exception : Exception - { - } - - /// - /// The short huffman data exception. - /// - private class ShortHuffmanDataException : Exception - { - } - - /// - /// The EOF (End of File exception). - /// Thrown when the decoder encounters an EOF marker without a proceeding EOI (End Of Image) marker - /// - private class EOFException : Exception - { - } - - public void Dispose() - { - scanWorkerBlock.Dispose(); - Block.DisposeAll(this.quantizationTables); - - foreach (Block[] blocks in progCoeffs) - { - if (blocks != null) - { - Block.DisposeAll(blocks); - } - } - - for (int i = 0; i < huffmanTrees.Length; i++) - { - huffmanTrees[i].Dispose(); - } - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegEncoder.cs b/src/ImageSharp46/Formats/Jpg/JpegEncoder.cs deleted file mode 100644 index 0fc1f3d35..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegEncoder.cs +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Encoder for writing the data image to a stream in jpeg format. - /// - public class JpegEncoder : IImageEncoder - { - /// - /// The quality used to encode the image. - /// - private int quality = 75; - - /// - /// The subsamples scheme used to encode the image. - /// - private JpegSubsample subsample = JpegSubsample.Ratio420; - - /// - /// Whether subsampling has been specifically set. - /// - private bool subsampleSet; - - /// - /// Gets or sets the quality, that will be used to encode the image. Quality - /// index must be between 0 and 100 (compression from max to min). - /// - /// - /// If the quality is less than or equal to 80, the subsampling ratio will switch to - /// - /// The quality of the jpg image from 0 to 100. - public int Quality - { - get { return this.quality; } - set { this.quality = value.Clamp(1, 100); } - } - - /// - /// Gets or sets the subsample ration, that will be used to encode the image. - /// - /// The subsample ratio of the jpg image. - public JpegSubsample Subsample - { - get - { - return this.subsample; - } - - set - { - this.subsample = value; - this.subsampleSet = true; - } - } - - /// - public string MimeType => "image/jpeg"; - - /// - public string Extension => "jpg"; - - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, "extension"); - - if (extension.StartsWith(".")) - { - extension = extension.Substring(1); - } - - return extension.Equals(this.Extension, StringComparison.OrdinalIgnoreCase) || - extension.Equals("jpeg", StringComparison.OrdinalIgnoreCase) || - extension.Equals("jfif", StringComparison.OrdinalIgnoreCase); - } - - /// - public void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - JpegEncoderCore encode = new JpegEncoderCore(); - if (this.subsampleSet) - { - encode.Encode(image, stream, this.Quality, this.Subsample); - } - else - { - encode.Encode(image, stream, this.Quality, this.Quality >= 80 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); - } - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs deleted file mode 100644 index 75e00bc76..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs +++ /dev/null @@ -1,1006 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Image encoder for writing an image to a stream as a jpeg. - /// - internal unsafe class JpegEncoderCore - { - /// - /// The number of quantization tables. - /// - private const int QuantizationTableCount = 2; - - /// - /// Maps from the zig-zag ordering to the natural ordering. For example, - /// unzig[3] is the column and row of the fourth element in zig-zag order. The - /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). - /// - private static readonly int[] Unzig = - { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, - 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, - 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, - 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, - }; - - /// - /// The Huffman encoding specifications. - /// This encoder uses the same Huffman encoding for all images. - /// - private static readonly HuffmanSpec[] TheHuffmanSpecs = - { - // Luminance DC. - new HuffmanSpec( - new byte[] - { - 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 - }, - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }), - new HuffmanSpec( - new byte[] - { - 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 - }, - new byte[] - { - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, - 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, - 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, - 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, - 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, - 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, - 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa - }), - new HuffmanSpec( - new byte[] - { - 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 - }, - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }), - - // Chrominance AC. - new HuffmanSpec( - new byte[] - { - 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 - }, - new byte[] - { - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, - 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, - 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, - 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, - 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, - 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, - 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, - 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa - }) - }; - - /// - /// The compiled representations of theHuffmanSpec. - /// - private static readonly HuffmanLut[] TheHuffmanLut = new HuffmanLut[4]; - - /// - /// Counts the number of bits needed to hold an integer. - /// - private readonly byte[] bitCountLut = - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, - }; - - /// - /// The unscaled quantization tables in zig-zag order. Each - /// encoder copies and scales the tables according to its quality parameter. - /// The values are derived from section K.1 after converting from natural to - /// zig-zag order. - /// - private readonly byte[,] unscaledQuant = - { - { - // Luminance. - 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, - 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, - 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, - 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, - 101, 103, 99, - }, - { - // Chrominance. - 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - } - }; - - /// - /// A scratch buffer to reduce allocations. - /// - private readonly byte[] buffer = new byte[16]; - - /// - /// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough. - /// - private readonly byte[] emitBuffer = new byte[64]; - - /// - /// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths + identifier. - /// - private readonly byte[] huffmanBuffer = new byte[179]; - - /// - /// The scaled quantization tables, in zig-zag order. - /// - private readonly byte[][] quant = new byte[QuantizationTableCount][]; - - /// - /// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes: - /// - the marker length "\x00\x0c", - /// - the number of components "\x03", - /// - component 1 uses DC table 0 and AC table 0 "\x01\x00", - /// - component 2 uses DC table 1 and AC table 1 "\x02\x11", - /// - component 3 uses DC table 1 and AC table 1 "\x03\x11", - /// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for - /// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al) - /// should be 0x00, 0x3f, 0x00<<4 | 0x00. - /// - private readonly byte[] sosHeaderYCbCr = - { - JpegConstants.Markers.XFF, JpegConstants.Markers.SOS, // Marker - 0x00, 0x0c, // Length (high byte, low byte), must be 6 + 2 * (number of components in scan) - 0x03, // Number of components in a scan, 3 - 0x01, // Component Id Y - 0x00, // DC/AC Huffman table - 0x02, // Component Id Cb - 0x11, // DC/AC Huffman table - 0x03, // Component Id Cr - 0x11, // DC/AC Huffman table - 0x00, // Ss - Start of spectral selection. - 0x3f, // Se - End of spectral selection. - 0x00 // Ah + Ah (Successive approximation bit position high + low) - }; - - /// - /// The accumulated bits to write to the stream. - /// - private uint accumulatedBits; - - /// - /// The accumulated bit count. - /// - private uint bitCount; - - /// - /// The output stream. All attempted writes after the first error become no-ops. - /// - private Stream outputStream; - - /// - /// The subsampling method to use. - /// - private JpegSubsample subsample; - - /// - /// Initializes static members of the class. - /// - static JpegEncoderCore() - { - // Initialize the Huffman tables - for (int i = 0; i < TheHuffmanSpecs.Length; i++) - { - TheHuffmanLut[i] = new HuffmanLut(TheHuffmanSpecs[i]); - } - } - - /// - /// Enumerates the Huffman tables - /// - private enum HuffIndex - { - /// - /// The DC luminance huffman table index - /// - LuminanceDC = 0, - - /// - /// The AC luminance huffman table index - /// - - LuminanceAC = 1, - // ReSharper restore UnusedMember.Local - - /// - /// The DC chrominance huffman table index - /// - ChrominanceDC = 2, - - /// - /// The AC chrominance huffman table index - /// - ChrominanceAC = 3, - } - - /// - /// Enumerates the quantization tables - /// - private enum QuantIndex - { - /// - /// The luminance quantization table index - /// - Luminance = 0, - - /// - /// The chrominance quantization table index - /// - Chrominance = 1, - } - - /// - /// Encode writes the image to the jpeg baseline format with the given options. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to write from. - /// The stream to write to. - /// The quality. - /// The subsampling mode. - public void Encode(Image image, Stream stream, int quality, JpegSubsample sample) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - ushort max = JpegConstants.MaxLength; - if (image.Width >= max || image.Height >= max) - { - throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}."); - } - - this.outputStream = stream; - this.subsample = sample; - - for (int i = 0; i < QuantizationTableCount; i++) - { - this.quant[i] = new byte[Block.BlockSize]; - } - - if (quality < 1) - { - quality = 1; - } - - if (quality > 100) - { - quality = 100; - } - - // Convert from a quality rating to a scaling factor. - int scale; - if (quality < 50) - { - scale = 5000 / quality; - } - else - { - scale = 200 - (quality * 2); - } - - // Initialize the quantization tables. - for (int i = 0; i < QuantizationTableCount; i++) - { - for (int j = 0; j < Block.BlockSize; j++) - { - int x = this.unscaledQuant[i, j]; - x = ((x * scale) + 50) / 100; - if (x < 1) - { - x = 1; - } - - if (x > 255) - { - x = 255; - } - - this.quant[i][j] = (byte)x; - } - } - - // Compute number of components based on input image type. - int componentCount = 3; - - // Write the Start Of Image marker. - this.WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution); - - this.WriteProfiles(image); - - // Write the quantization tables. - this.WriteDefineQuantizationTables(); - - // Write the image dimensions. - this.WriteStartOfFrame(image.Width, image.Height, componentCount); - - // Write the Huffman tables. - this.WriteDefineHuffmanTables(componentCount); - - // Write the image data. - using (PixelAccessor pixels = image.Lock()) - { - this.WriteStartOfScan(pixels); - } - - // Write the End Of Image marker. - this.buffer[0] = JpegConstants.Markers.XFF; - this.buffer[1] = JpegConstants.Markers.EOI; - stream.Write(this.buffer, 0, 2); - stream.Flush(); - } - - /// - /// Gets the quotient of the two numbers rounded to the nearest integer, instead of rounded to zero. - /// - /// The value to divide. - /// The value to divide by. - /// The - private static int Round(int dividend, int divisor) - { - if (dividend >= 0) - { - return (dividend + (divisor >> 1)) / divisor; - } - - return -((-dividend + (divisor >> 1)) / divisor); - } - - /// - /// Emits the least significant count of bits of bits to the bit-stream. - /// The precondition is bits < 1<<nBits && nBits <= 16. - /// - /// The packed bits. - /// The number of bits - private void Emit(uint bits, uint count) - { - count += this.bitCount; - bits <<= (int)(32 - count); - bits |= this.accumulatedBits; - - // Only write if more than 8 bits. - if (count >= 8) - { - // Track length - int len = 0; - while (count >= 8) - { - byte b = (byte)(bits >> 24); - this.emitBuffer[len++] = b; - if (b == 0xff) - { - this.emitBuffer[len++] = 0x00; - } - - bits <<= 8; - count -= 8; - } - - if (len > 0) - { - this.outputStream.Write(this.emitBuffer, 0, len); - } - } - - this.accumulatedBits = bits; - this.bitCount = count; - } - - /// - /// Emits the given value with the given Huffman encoder. - /// - /// The index of the Huffman encoder - /// The value to encode. - private void EmitHuff(HuffIndex index, int value) - { - uint x = TheHuffmanLut[(int)index].Values[value]; - this.Emit(x & ((1 << 24) - 1), x >> 24); - } - - /// - /// Emits a run of runLength copies of value encoded with the given Huffman encoder. - /// - /// The index of the Huffman encoder - /// The number of copies to encode. - /// The value to encode. - private void EmitHuffRLE(HuffIndex index, int runLength, int value) - { - int a = value; - int b = value; - if (a < 0) - { - a = -value; - b = value - 1; - } - - uint bt; - if (a < 0x100) - { - bt = this.bitCountLut[a]; - } - else - { - bt = 8 + (uint)this.bitCountLut[a >> 8]; - } - - this.EmitHuff(index, (int)((uint)(runLength << 4) | bt)); - if (bt > 0) - { - this.Emit((uint)b & (uint)((1 << ((int)bt)) - 1), bt); - } - } - - /// - /// Writes a block of pixel data using the given quantization table, - /// returning the post-quantized DC value of the DCT-transformed block. - /// The block is in natural (not zig-zag) order. - /// - /// The block to write. - /// The quantization table index. - /// The previous DC value. - /// The - private int WriteBlock(ref Block block, QuantIndex index, int prevDC) - { - FDCT.Transform(ref block); - - // Emit the DC delta. - int dc = Round(block[0], 8 * this.quant[(int)index][0]); - this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC); - - // Emit the AC components. - HuffIndex h = (HuffIndex)((2 * (int)index) + 1); - int runLength = 0; - - for (int zig = 1; zig < Block.BlockSize; zig++) - { - int ac = Round(block[Unzig[zig]], 8 * this.quant[(int)index][zig]); - - if (ac == 0) - { - runLength++; - } - else - { - while (runLength > 15) - { - this.EmitHuff(h, 0xf0); - runLength -= 16; - } - - this.EmitHuffRLE(h, runLength, ac); - runLength = 0; - } - } - - if (runLength > 0) - { - this.EmitHuff(h, 0x00); - } - - return dc; - } - - /// - /// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The pixel accessor. - /// The x-position within the image. - /// The y-position within the image. - /// The luminance block. - /// The red chroma block. - /// The blue chroma block. - // ReSharper disable StyleCop.SA1305 - private void ToYCbCr(PixelAccessor pixels, int x, int y, - ref Block yBlock, ref Block cbBlock, ref Block crBlock) - // ReSharper restore StyleCop.SA1305 - where TColor : struct, IPackedPixel - where TPacked : struct - { - int xmax = pixels.Width - 1; - int ymax = pixels.Height - 1; - byte[] color = new byte[3]; - for (int j = 0; j < 8; j++) - { - for (int i = 0; i < 8; i++) - { - pixels[Math.Min(x + i, xmax), Math.Min(y + j, ymax)].ToBytes(color, 0, ComponentOrder.XYZ); - - byte r = color[0]; - byte g = color[1]; - byte b = color[2]; - - // Convert returned bytes into the YCbCr color space. Assume RGBA - byte yy = (byte)((0.299F * r) + (0.587F * g) + (0.114F * b)); - byte cb = (byte)(128 + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b))); - byte cr = (byte)(128 + ((0.5F * r) - (0.418688F * g) - (0.081312F * b))); - - int index = (8 * j) + i; - yBlock[index] = yy; - cbBlock[index] = cb; - crBlock[index] = cr; - } - } - } - - /// - /// Scales the 16x16 region represented by the 4 source blocks to the 8x8 - /// DST block. - /// - /// The destination block array - /// The source block array. - private void Scale16X16To8X8(ref Block destination, Block[] source) - { - for (int i = 0; i < 4; i++) - { - int dstOff = ((i & 2) << 4) | ((i & 1) << 2); - for (int y = 0; y < 4; y++) - { - for (int x = 0; x < 4; x++) - { - int j = (16 * y) + (2 * x); - int sum = source[i][j] + source[i][j + 1] + source[i][j + 8] + source[i][j + 9]; - destination[(8 * y) + x + dstOff] = (sum + 2) / 4; - } - } - } - } - - /// - /// Writes the application header containing the JFIF identifier plus extra data. - /// - /// The resolution of the image in the x- direction. - /// The resolution of the image in the y- direction. - private void WriteApplicationHeader(short horizontalResolution, short verticalResolution) - { - // Write the start of image marker. Markers are always prefixed with with 0xff. - this.buffer[0] = JpegConstants.Markers.XFF; - this.buffer[1] = JpegConstants.Markers.SOI; - - // Write the JFIF headers - this.buffer[2] = JpegConstants.Markers.XFF; - this.buffer[3] = JpegConstants.Markers.APP0; // Application Marker - this.buffer[4] = 0x00; - this.buffer[5] = 0x10; - this.buffer[6] = 0x4a; // J - this.buffer[7] = 0x46; // F - this.buffer[8] = 0x49; // I - this.buffer[9] = 0x46; // F - this.buffer[10] = 0x00; // = "JFIF",'\0' - this.buffer[11] = 0x01; // versionhi - this.buffer[12] = 0x01; // versionlo - this.buffer[13] = 0x01; // xyunits as dpi - - // No thumbnail - this.buffer[14] = 0x00; // Thumbnail width - this.buffer[15] = 0x00; // Thumbnail height - - this.outputStream.Write(this.buffer, 0, 16); - - // Resolution. Big Endian - this.buffer[0] = (byte)(horizontalResolution >> 8); - this.buffer[1] = (byte)horizontalResolution; - this.buffer[2] = (byte)(verticalResolution >> 8); - this.buffer[3] = (byte)verticalResolution; - - this.outputStream.Write(this.buffer, 0, 4); - } - - /// - /// Writes the metadata profiles to the image. - /// - /// The image. - /// The pixel format. - /// The packed format. uint, long, float. - private void WriteProfiles(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - this.WriteProfile(image.ExifProfile); - } - - /// - /// Writes the EXIF profile. - /// - /// The exif profile. - /// - /// Thrown if the EXIF profile size exceeds the limit - /// - private void WriteProfile(ExifProfile exifProfile) - { - const int Max = 65533; - byte[] data = exifProfile?.ToByteArray(); - if (data == null || data.Length == 0) - { - return; - } - - if (data.Length > Max) - { - throw new ImageFormatException($"Exif profile size exceeds limit. nameof{Max}"); - } - - int length = data.Length + 2; - - this.buffer[0] = JpegConstants.Markers.XFF; - this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker - this.buffer[2] = (byte)((length >> 8) & 0xFF); - this.buffer[3] = (byte)(length & 0xFF); - - this.outputStream.Write(this.buffer, 0, 4); - this.outputStream.Write(data, 0, data.Length); - } - - /// - /// Writes the Define Quantization Marker and tables. - /// - private void WriteDefineQuantizationTables() - { - // Marker + quantization table lengths - int markerlen = 2 + (QuantizationTableCount * (1 + Block.BlockSize)); - this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen); - - // Loop through and collect the tables as one array. - // This allows us to reduce the number of writes to the stream. - byte[] dqt = new byte[(QuantizationTableCount * Block.BlockSize) + QuantizationTableCount]; - int offset = 0; - for (int i = 0; i < QuantizationTableCount; i++) - { - dqt[offset++] = (byte)i; - int len = this.quant[i].Length; - for (int j = 0; j < len; j++) - { - dqt[offset++] = this.quant[i][j]; - } - } - - this.outputStream.Write(dqt, 0, dqt.Length); - } - - /// - /// Writes the Start Of Frame (Baseline) marker - /// - /// The width of the image - /// The height of the image - /// The number of components in a pixel - private void WriteStartOfFrame(int width, int height, int componentCount) - { - // "default" to 4:2:0 - byte[] subsamples = { 0x22, 0x11, 0x11 }; - byte[] chroma = { 0x00, 0x01, 0x01 }; - - switch (this.subsample) - { - case JpegSubsample.Ratio444: - subsamples = new byte[] { 0x11, 0x11, 0x11 }; - break; - case JpegSubsample.Ratio420: - subsamples = new byte[] { 0x22, 0x11, 0x11 }; - break; - } - - // Length (high byte, low byte), 8 + components * 3. - int markerlen = 8 + (3 * componentCount); - this.WriteMarkerHeader(JpegConstants.Markers.SOF0, markerlen); - this.buffer[0] = 8; // Data Precision. 8 for now, 12 and 16 bit jpegs not supported - this.buffer[1] = (byte)(height >> 8); - this.buffer[2] = (byte)(height & 0xff); // (2 bytes, Hi-Lo), must be > 0 if DNL not supported - this.buffer[3] = (byte)(width >> 8); - this.buffer[4] = (byte)(width & 0xff); // (2 bytes, Hi-Lo), must be > 0 if DNL not supported - this.buffer[5] = (byte)componentCount; // Number of components (1 byte), usually 1 = Gray scaled, 3 = color YCbCr or YIQ, 4 = color CMYK) - if (componentCount == 1) - { - this.buffer[6] = 1; - - // No subsampling for grayscale images. - this.buffer[7] = 0x11; - this.buffer[8] = 0x00; - } - else - { - for (int i = 0; i < componentCount; i++) - { - this.buffer[(3 * i) + 6] = (byte)(i + 1); - - // We use 4:2:0 chroma subsampling by default. - this.buffer[(3 * i) + 7] = subsamples[i]; - this.buffer[(3 * i) + 8] = chroma[i]; - } - } - - this.outputStream.Write(this.buffer, 0, (3 * (componentCount - 1)) + 9); - } - - /// - /// Writes the Define Huffman Table marker and tables. - /// - /// The number of components to write. - private void WriteDefineHuffmanTables(int componentCount) - { - // Table identifiers. - byte[] headers = { 0x00, 0x10, 0x01, 0x11 }; - int markerlen = 2; - HuffmanSpec[] specs = TheHuffmanSpecs; - - if (componentCount == 1) - { - // Drop the Chrominance tables. - specs = new[] { TheHuffmanSpecs[0], TheHuffmanSpecs[1] }; - } - - foreach (HuffmanSpec s in specs) - { - markerlen += 1 + 16 + s.Values.Length; - } - - this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen); - for (int i = 0; i < specs.Length; i++) - { - HuffmanSpec spec = specs[i]; - int len = 0; - - fixed (byte* huffman = this.huffmanBuffer) - fixed (byte* count = spec.Count) - fixed (byte* values = spec.Values) - { - huffman[len++] = headers[i]; - - for (int c = 0; c < spec.Count.Length; c++) - { - huffman[len++] = count[c]; - } - - for (int v = 0; v < spec.Values.Length; v++) - { - huffman[len++] = values[v]; - } - } - - this.outputStream.Write(this.huffmanBuffer, 0, len); - } - } - - /// - /// Writes the StartOfScan marker. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// - /// The pixel accessor providing access to the image pixels. - /// - private void WriteStartOfScan(PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // TODO: We should allow grayscale writing. - this.outputStream.Write(this.sosHeaderYCbCr, 0, this.sosHeaderYCbCr.Length); - - switch (this.subsample) - { - case JpegSubsample.Ratio444: - this.Encode444(pixels); - break; - case JpegSubsample.Ratio420: - this.Encode420(pixels); - break; - } - - // Pad the last byte with 1's. - this.Emit(0x7f, 7); - } - - /// - /// Encodes the image with no subsampling. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The pixel accessor providing access to the image pixels. - private void Encode444(PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Block b = Block.Create(); - Block cb = Block.Create(); - Block cr = Block.Create(); - // ReSharper disable once InconsistentNaming - int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - - for (int y = 0; y < pixels.Height; y += 8) - { - for (int x = 0; x < pixels.Width; x += 8) - { - this.ToYCbCr(pixels, x, y, ref b, ref cb, ref cr); - prevDCY = this.WriteBlock(ref b, QuantIndex.Luminance, prevDCY); - prevDCCb = this.WriteBlock(ref cb, QuantIndex.Chrominance, prevDCCb); - prevDCCr = this.WriteBlock(ref cr, QuantIndex.Chrominance, prevDCCr); - } - } - b.Dispose(); - cb.Dispose(); - cr.Dispose(); - } - - /// - /// Encodes the image with subsampling. The Cb and Cr components are each subsampled - /// at a factor of 2 both horizontally and vertically. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The pixel accessor providing access to the image pixels. - private void Encode420(PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Block b = Block.Create(); - Block[] cb = Block.CreateArray(4); - Block[] cr = Block.CreateArray(4); - // ReSharper disable once InconsistentNaming - int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - - for (int y = 0; y < pixels.Height; y += 16) - { - for (int x = 0; x < pixels.Width; x += 16) - { - for (int i = 0; i < 4; i++) - { - int xOff = (i & 1) * 8; - int yOff = (i & 2) * 4; - - this.ToYCbCr(pixels, x + xOff, y + yOff, ref b, ref cb[i], ref cr[i]); - prevDCY = this.WriteBlock(ref b, QuantIndex.Luminance, prevDCY); - } - - this.Scale16X16To8X8(ref b, cb); - prevDCCb = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCb); - this.Scale16X16To8X8(ref b, cr); - prevDCCr = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCr); - } - } - - b.Dispose(); - Block.DisposeAll(cb); - Block.DisposeAll(cr); - } - - /// - /// Writes the header for a marker with the given length. - /// - /// The marker to write. - /// The marker length. - private void WriteMarkerHeader(byte marker, int length) - { - // Markers are always prefixed with with 0xff. - this.buffer[0] = JpegConstants.Markers.XFF; - this.buffer[1] = marker; - this.buffer[2] = (byte)(length >> 8); - this.buffer[3] = (byte)(length & 0xff); - this.outputStream.Write(this.buffer, 0, 4); - } - - /// - /// The Huffman encoding specifications. - /// - private struct HuffmanSpec - { - /// - /// Gets count[i] - The number of codes of length i bits. - /// - public readonly byte[] Count; - - /// - /// Gets value[i] - The decoded value of the codeword at the given index. - /// - public readonly byte[] Values; - - /// - /// Initializes a new instance of the struct. - /// - /// The number of codes. - /// The decoded values. - public HuffmanSpec(byte[] count, byte[] values) - { - this.Count = count; - this.Values = values; - } - } - - /// - /// A compiled look-up table representation of a huffmanSpec. - /// Each value maps to a uint32 of which the 8 most significant bits hold the - /// codeword size in bits and the 24 least significant bits hold the codeword. - /// The maximum codeword size is 16 bits. - /// - private class HuffmanLut - { - /// - /// The collection of huffman values. - /// - public readonly uint[] Values; - - /// - /// Initializes a new instance of the class. - /// - /// The encoding specifications. - public HuffmanLut(HuffmanSpec spec) - { - int maxValue = 0; - - foreach (byte v in spec.Values) - { - if (v > maxValue) - { - maxValue = v; - } - } - - this.Values = new uint[maxValue + 1]; - - int code = 0; - int k = 0; - - for (int i = 0; i < spec.Count.Length; i++) - { - int bits = (i + 1) << 24; - for (int j = 0; j < spec.Count[i]; j++) - { - this.Values[spec.Values[k]] = (uint)(bits | code); - code++; - k++; - } - - code <<= 1; - } - } - } - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegFormat.cs b/src/ImageSharp46/Formats/Jpg/JpegFormat.cs deleted file mode 100644 index 0e2ff7949..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegFormat.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Encapsulates the means to encode and decode jpeg images. - /// - public class JpegFormat : IImageFormat - { - /// - public IImageDecoder Decoder => new JpegDecoder(); - - /// - public IImageEncoder Encoder => new JpegEncoder(); - } -} diff --git a/src/ImageSharp46/Formats/Jpg/JpegSubsample.cs b/src/ImageSharp46/Formats/Jpg/JpegSubsample.cs deleted file mode 100644 index 287323bdd..000000000 --- a/src/ImageSharp46/Formats/Jpg/JpegSubsample.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Enumerates the chroma subsampling method applied to the image. - /// - public enum JpegSubsample - { - /// - /// High Quality - Each of the three Y'CbCr components have the same sample rate, - /// thus there is no chroma subsampling. - /// - Ratio444, - - /// - /// Medium Quality - The horizontal sampling is halved and the Cb and Cr channels are only - /// sampled on each alternate line. - /// - Ratio420 - } -} diff --git a/src/ImageSharp46/Formats/Jpg/README.md b/src/ImageSharp46/Formats/Jpg/README.md deleted file mode 100644 index 54bc14847..000000000 --- a/src/ImageSharp46/Formats/Jpg/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Encoder/Decoder adapted and extended from: - -https://golang.org/src/image/jpeg/ \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp46/Formats/Png/Filters/AverageFilter.cs deleted file mode 100644 index bef124541..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/AverageFilter.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// The Average filter uses the average of the two neighboring pixels (left and above) to predict - /// the value of a pixel. - /// - /// - internal static class AverageFilter - { - /// - /// Decodes the scanline - /// - /// The scanline to decode - /// The previous scanline. - /// The bytes per pixel. - /// - /// The - /// - public static byte[] Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) - { - // Average(x) + floor((Raw(x-bpp)+Prior(x))/2) - byte[] result = new byte[scanline.Length]; - - for (int x = 1; x < scanline.Length; x++) - { - byte left = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; - byte above = previousScanline[x]; - - result[x] = (byte)((scanline[x] + Average(left, above)) % 256); - } - - return result; - } - - /// - /// Encodes the scanline - /// - /// The scanline to encode - /// The previous scanline. - /// The bytes per pixel. - /// The number of bytes per scanline - /// The - public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel, int bytesPerScanline) - { - // Average(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - - encodedScanline[0] = (byte)FilterType.Average; - - for (int x = 0; x < bytesPerScanline; x++) - { - byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; - byte above = previousScanline[x]; - - encodedScanline[x + 1] = (byte)((scanline[x] - Average(left, above)) % 256); - } - - return encodedScanline; - } - - /// - /// Calculates the average value of two bytes - /// - /// The left byte - /// The above byte - /// The - private static int Average(byte left, byte above) - { - return Convert.ToInt32(Math.Floor((left + above) / 2.0D)); - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Filters/FilterType.cs b/src/ImageSharp46/Formats/Png/Filters/FilterType.cs deleted file mode 100644 index 0eddf08f2..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/FilterType.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Provides enumeration of the various PNG filter types. - /// - /// - internal enum FilterType - { - /// - /// With the None filter, the scanline is transmitted unmodified; it is only necessary to - /// insert a filter type byte before the data. - /// - None = 0, - - /// - /// The Sub filter transmits the difference between each byte and the value of the corresponding - /// byte of the prior pixel. - /// - Sub = 1, - - /// - /// The Up filter is just like the Sub filter except that the pixel immediately above the current - /// pixel, rather than just to its left, is used as the predictor. - /// - Up = 2, - - /// - /// The Average filter uses the average of the two neighboring pixels (left and above) to - /// predict the value of a pixel. - /// - Average = 3, - - /// - /// The Paeth filter computes a simple linear function of the three neighboring pixels (left, above, upper left), - /// then chooses as predictor the neighboring pixel closest to the computed value. - /// This technique is due to Alan W. Paeth - /// - Paeth = 4 - } -} diff --git a/src/ImageSharp46/Formats/Png/Filters/NoneFilter.cs b/src/ImageSharp46/Formats/Png/Filters/NoneFilter.cs deleted file mode 100644 index 175e5affa..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/NoneFilter.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// The None filter, the scanline is transmitted unmodified; it is only necessary to - /// insert a filter type byte before the data. - /// - /// - internal static class NoneFilter - { - /// - /// Decodes the scanline - /// - /// The scanline to decode - /// The - public static byte[] Decode(byte[] scanline) - { - // No change required. - return scanline; - } - - /// - /// Encodes the scanline - /// - /// The scanline to encode - /// The number of bytes per scanline - /// The - public static byte[] Encode(byte[] scanline, int bytesPerScanline) - { - // Insert a byte before the data. - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.None; - Buffer.BlockCopy(scanline, 0, encodedScanline, 1, bytesPerScanline); - - return encodedScanline; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp46/Formats/Png/Filters/PaethFilter.cs deleted file mode 100644 index 232d7cc3d..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/PaethFilter.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// The Paeth filter computes a simple linear function of the three neighboring pixels (left, above, upper left), - /// then chooses as predictor the neighboring pixel closest to the computed value. - /// This technique is due to Alan W. Paeth. - /// - /// - internal static class PaethFilter - { - /// - /// Decodes the scanline - /// - /// The scanline to decode - /// The previous scanline. - /// The bytes per pixel. - /// The - public static byte[] Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) - { - // Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) - byte[] result = new byte[scanline.Length]; - - for (int x = 1; x < scanline.Length; x++) - { - byte left = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; - byte above = previousScanline[x]; - byte upperLeft = (x - bytesPerPixel < 1) ? (byte)0 : previousScanline[x - bytesPerPixel]; - - result[x] = (byte)((scanline[x] + PaethPredicator(left, above, upperLeft)) % 256); - } - - return result; - } - - /// - /// Encodes the scanline - /// - /// The scanline to encode - /// The previous scanline. - /// The bytes per pixel. - /// The number of bytes per scanline - /// The - public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel, int bytesPerScanline) - { - // Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x - bpp)) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Paeth; - - for (int x = 0; x < bytesPerScanline; x++) - { - byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; - byte above = previousScanline[x]; - byte upperLeft = (x - bytesPerPixel < 0) ? (byte)0 : previousScanline[x - bytesPerPixel]; - - encodedScanline[x + 1] = (byte)((scanline[x] - PaethPredicator(left, above, upperLeft)) % 256); - } - - return encodedScanline; - } - - /// - /// Computes a simple linear function of the three neighboring pixels (left, above, upper left), then chooses - /// as predictor the neighboring pixel closest to the computed value. - /// - /// The left neighbor pixel. - /// The above neighbor pixel. - /// The upper left neighbor pixel. - /// - /// The . - /// - private static byte PaethPredicator(byte left, byte above, byte upperLeft) - { - int p = left + above - upperLeft; - int pa = Math.Abs(p - left); - int pb = Math.Abs(p - above); - int pc = Math.Abs(p - upperLeft); - - if (pa <= pb && pa <= pc) - { - return left; - } - - if (pb <= pc) - { - return above; - } - - return upperLeft; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp46/Formats/Png/Filters/SubFilter.cs deleted file mode 100644 index c4fbe3e51..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/SubFilter.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// The Sub filter transmits the difference between each byte and the value of the corresponding byte - /// of the prior pixel. - /// - /// - internal static class SubFilter - { - /// - /// Decodes the scanline - /// - /// The scanline to decode - /// The bytes per pixel. - /// The - public static byte[] Decode(byte[] scanline, int bytesPerPixel) - { - // Sub(x) + Raw(x-bpp) - byte[] result = new byte[scanline.Length]; - - for (int x = 1; x < scanline.Length; x++) - { - byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; - - result[x] = (byte)((scanline[x] + priorRawByte) % 256); - } - - return result; - } - - /// - /// Encodes the scanline - /// - /// The scanline to encode - /// The bytes per pixel. - /// The number of bytes per scanline - /// The - public static byte[] Encode(byte[] scanline, int bytesPerPixel, int bytesPerScanline) - { - // Sub(x) = Raw(x) - Raw(x-bpp) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Sub; - - for (int x = 0; x < bytesPerScanline; x++) - { - byte priorRawByte = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; - - encodedScanline[x + 1] = (byte)((scanline[x] - priorRawByte) % 256); - } - - return encodedScanline; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp46/Formats/Png/Filters/UpFilter.cs deleted file mode 100644 index 026070421..000000000 --- a/src/ImageSharp46/Formats/Png/Filters/UpFilter.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// The Up filter is just like the Sub filter except that the pixel immediately above the current pixel, - /// rather than just to its left, is used as the predictor. - /// - /// - internal static class UpFilter - { - /// - /// Decodes the scanline - /// - /// The scanline to decode - /// The previous scanline. - /// The - public static byte[] Decode(byte[] scanline, byte[] previousScanline) - { - // Up(x) + Prior(x) - byte[] result = new byte[scanline.Length]; - - for (int x = 1; x < scanline.Length; x++) - { - byte above = previousScanline[x]; - - result[x] = (byte)((scanline[x] + above) % 256); - } - - return result; - } - - /// - /// Encodes the scanline - /// - /// The scanline to encode - /// The number of bytes per scanline - /// The previous scanline. - /// The - public static byte[] Encode(byte[] scanline, int bytesPerScanline, byte[] previousScanline) - { - // Up(x) = Raw(x) - Prior(x) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Up; - - for (int x = 0; x < bytesPerScanline; x++) - { - byte above = previousScanline[x]; - - encodedScanline[x + 1] = (byte)((scanline[x] - above) % 256); - } - - return encodedScanline; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngChunk.cs b/src/ImageSharp46/Formats/Png/PngChunk.cs deleted file mode 100644 index 3d769057c..000000000 --- a/src/ImageSharp46/Formats/Png/PngChunk.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Stores header information about a chunk. - /// - internal sealed class PngChunk - { - /// - /// Gets or sets the length. - /// An unsigned integer giving the number of bytes in the chunk's - /// data field. The length counts only the data field, not itself, - /// the chunk type code, or the CRC. Zero is a valid length - /// - public int Length { get; set; } - - /// - /// Gets or sets the chunk type as string with 4 chars. - /// - public string Type { get; set; } - - /// - /// Gets or sets the data bytes appropriate to the chunk type, if any. - /// This field can be of zero length. - /// - public byte[] Data { get; set; } - - /// - /// Gets or sets a CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk, - /// including the chunk type code and chunk data fields, but not including the length field. - /// The CRC is always present, even for chunks containing no data - /// - public uint Crc { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngChunkTypes.cs b/src/ImageSharp46/Formats/Png/PngChunkTypes.cs deleted file mode 100644 index 72486b50d..000000000 --- a/src/ImageSharp46/Formats/Png/PngChunkTypes.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Contains a list of possible chunk type identifiers. - /// - internal static class PngChunkTypes - { - /// - /// The first chunk in a png file. Can only exists once. Contains - /// common information like the width and the height of the image or - /// the used compression method. - /// - public const string Header = "IHDR"; - - /// - /// The PLTE chunk contains from 1 to 256 palette entries, each a three byte - /// series in the RGB format. - /// - public const string Palette = "PLTE"; - - /// - /// The IDAT chunk contains the actual image data. The image can contains more - /// than one chunk of this type. All chunks together are the whole image. - /// - public const string Data = "IDAT"; - - /// - /// This chunk must appear last. It marks the end of the PNG data stream. - /// The chunk's data field is empty. - /// - public const string End = "IEND"; - - /// - /// This chunk specifies that the image uses simple transparency: - /// either alpha values associated with palette entries (for indexed-color images) - /// or a single transparent color (for grayscale and true color images). - /// - public const string PaletteAlpha = "tRNS"; - - /// - /// Textual information that the encoder wishes to record with the image can be stored in - /// tEXt chunks. Each tEXt chunk contains a keyword and a text string. - /// - public const string Text = "tEXt"; - - /// - /// This chunk specifies the relationship between the image samples and the desired - /// display output intensity. - /// - public const string Gamma = "gAMA"; - - /// - /// The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image. - /// - public const string Physical = "pHYs"; - } -} diff --git a/src/ImageSharp46/Formats/Png/PngColorType.cs b/src/ImageSharp46/Formats/Png/PngColorType.cs deleted file mode 100644 index 421e27ba3..000000000 --- a/src/ImageSharp46/Formats/Png/PngColorType.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Provides enumeration of available PNG color types. - /// - public enum PngColorType : byte - { - /// - /// Each pixel is a grayscale sample. - /// - Grayscale = 0, - - /// - /// Each pixel is an R,G,B triple. - /// - Rgb = 2, - - /// - /// Each pixel is a palette index; a PLTE chunk must appear. - /// - Palette = 3, - - /// - /// Each pixel is a grayscale sample, followed by an alpha sample. - /// - GrayscaleWithAlpha = 4, - - /// - /// Each pixel is an R,G,B triple, followed by an alpha sample. - /// - RgbWithAlpha = 6 - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Png/PngDecoder.cs b/src/ImageSharp46/Formats/Png/PngDecoder.cs deleted file mode 100644 index 08e086a43..000000000 --- a/src/ImageSharp46/Formats/Png/PngDecoder.cs +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - /// - /// Encoder for generating an image out of a png encoded stream. - /// - /// - /// At the moment the following features are supported: - /// - /// Filters: all filters are supported. - /// - /// - /// Pixel formats: - /// - /// RGBA (True color) with alpha (8 bit). - /// RGB (True color) without alpha (8 bit). - /// Grayscale with alpha (8 bit). - /// Grayscale without alpha (8 bit). - /// Palette Index with alpha (8 bit). - /// Palette Index without alpha (8 bit). - /// - /// - /// - public class PngDecoder : IImageDecoder - { - /// - /// Gets the size of the header for this image type. - /// - /// The size of the header. - public int HeaderSize => 8; - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file extension. - /// - /// True if the decoder supports the file extension; otherwise, false. - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, "extension"); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - - return extension.Equals("PNG", StringComparison.OrdinalIgnoreCase); - } - - /// - /// Returns a value indicating whether the supports the specified - /// file header. - /// - /// The containing the file header. - /// - /// True if the decoder supports the file header; otherwise, false. - /// - public bool IsSupportedFileFormat(byte[] header) - { - return header.Length >= 8 && - header[0] == 0x89 && - header[1] == 0x50 && // P - header[2] == 0x4E && // N - header[3] == 0x47 && // G - header[4] == 0x0D && // CR - header[5] == 0x0A && // LF - header[6] == 0x1A && // EOF - header[7] == 0x0A; // LF - } - - /// - /// Decodes the image from the specified stream to the . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to decode to. - /// The containing image data. - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - new PngDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngDecoderCore.cs b/src/ImageSharp46/Formats/Png/PngDecoderCore.cs deleted file mode 100644 index cad32d9f2..000000000 --- a/src/ImageSharp46/Formats/Png/PngDecoderCore.cs +++ /dev/null @@ -1,645 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - - /// - /// Performs the png decoding operation. - /// - internal class PngDecoderCore - { - /// - /// The dictionary of available color types. - /// - private static readonly Dictionary ColorTypes = new Dictionary(); - - /// - /// Reusable buffer for reading chunk types. - /// - private readonly byte[] chunkTypeBuffer = new byte[4]; - - /// - /// Reusable buffer for reading chunk lengths. - /// - private readonly byte[] chunkLengthBuffer = new byte[4]; - - /// - /// Reusable buffer for reading crc values. - /// - private readonly byte[] crcBuffer = new byte[4]; - - /// - /// Reusable buffer for reading char arrays. - /// - private readonly char[] chars = new char[4]; - - /// - /// The stream to decode from. - /// - private Stream currentStream; - - /// - /// The png header. - /// - private PngHeader header; - - /// - /// The number of bytes per pixel. - /// - private int bytesPerPixel; - - /// - /// The number of bytes per sample - /// - private int bytesPerSample; - - /// - /// The number of bytes per scanline - /// - private int bytesPerScanline; - - /// - /// The palette containing color information for indexed png's - /// - private byte[] palette; - - /// - /// The palette containing alpha channel color information for indexed png's - /// - private byte[] paletteAlpha; - - /// - /// Initializes static members of the class. - /// - static PngDecoderCore() - { - ColorTypes.Add((int)PngColorType.Grayscale, new byte[] { 1, 2, 4, 8 }); - - ColorTypes.Add((int)PngColorType.Rgb, new byte[] { 8 }); - - ColorTypes.Add((int)PngColorType.Palette, new byte[] { 1, 2, 4, 8 }); - - ColorTypes.Add((int)PngColorType.GrayscaleWithAlpha, new byte[] { 8 }); - - ColorTypes.Add((int)PngColorType.RgbWithAlpha, new byte[] { 8 }); - } - - /// - /// Gets or sets the png color type - /// - public PngColorType PngColorType { get; set; } - - /// - /// Decodes the stream to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to decode to. - /// The stream containing image data. - /// - /// Thrown if the stream does not contain and end chunk. - /// - /// - /// Thrown if the image is larger than the maximum allowable size. - /// - public void Decode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Image currentImage = image; - this.currentStream = stream; - this.currentStream.Skip(8); - - bool isEndChunkReached = false; - - using (MemoryStream dataStream = new MemoryStream()) - { - PngChunk currentChunk; - while ((currentChunk = this.ReadChunk()) != null) - { - if (isEndChunkReached) - { - throw new ImageFormatException("Image does not end with end chunk."); - } - - switch (currentChunk.Type) - { - case PngChunkTypes.Header: - this.ReadHeaderChunk(currentChunk.Data); - this.ValidateHeader(); - break; - case PngChunkTypes.Physical: - this.ReadPhysicalChunk(currentImage, currentChunk.Data); - break; - case PngChunkTypes.Data: - dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length); - break; - case PngChunkTypes.Palette: - this.palette = currentChunk.Data; - image.Quality = this.palette.Length / 3; - break; - case PngChunkTypes.PaletteAlpha: - this.paletteAlpha = currentChunk.Data; - break; - case PngChunkTypes.Text: - this.ReadTextChunk(currentImage, currentChunk.Data); - break; - case PngChunkTypes.End: - isEndChunkReached = true; - break; - } - } - - if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight) - { - throw new ArgumentOutOfRangeException( - $"The input png '{this.header.Width}x{this.header.Height}' is bigger than the " - + $"max allowed size '{image.MaxWidth}x{image.MaxHeight}'"); - } - - image.InitPixels(this.header.Width, this.header.Height); - - using (PixelAccessor pixels = image.Lock()) - { - this.ReadScanlines(dataStream, pixels); - } - } - } - - /// - /// Reads the data chunk containing physical dimension data. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to read to. - /// The data containing physical data. - private void ReadPhysicalChunk(Image image, byte[] data) - where TColor : struct, IPackedPixel - where TPacked : struct - { - data.ReverseBytes(0, 4); - data.ReverseBytes(4, 4); - - // 39.3700787 = inches in a meter. - image.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d; - image.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d; - } - - /// - /// Calculates the correct number of bytes per pixel for the given color type. - /// - /// The - private int CalculateBytesPerPixel() - { - switch (this.PngColorType) - { - case PngColorType.Grayscale: - return 1; - - case PngColorType.GrayscaleWithAlpha: - return 2; - - case PngColorType.Palette: - return 1; - - case PngColorType.Rgb: - return 3; - - // PngColorType.RgbWithAlpha: - default: - return 4; - } - } - - /// - /// Calculates the scanline length. - /// - /// The representing the length. - private int CalculateScanlineLength() - { - int scanlineLength = this.header.Width * this.header.BitDepth * this.bytesPerPixel; - - int amount = scanlineLength % 8; - if (amount != 0) - { - scanlineLength += 8 - amount; - } - - return scanlineLength / 8; - } - - /// - /// Reads the scanlines within the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing data. - /// The pixel data. - private void ReadScanlines(MemoryStream dataStream, PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - this.bytesPerPixel = this.CalculateBytesPerPixel(); - this.bytesPerScanline = this.CalculateScanlineLength() + 1; - this.bytesPerSample = 1; - if (this.header.BitDepth >= 8) - { - this.bytesPerSample = this.header.BitDepth / 8; - } - - dataStream.Position = 0; - using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream)) - { - this.DecodePixelData(compressedStream, pixels); - } - } - - /// - /// Decodes the raw pixel data row by row - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The compressed pixel data stream. - /// The image pixel accessor. - private void DecodePixelData(Stream compressedStream, PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // TODO: ArrayPool.Shared.Rent(this.bytesPerScanline) - byte[] previousScanline = new byte[this.bytesPerScanline]; - byte[] scanline = new byte[this.bytesPerScanline]; - for (int y = 0; y < this.header.Height; y++) - { - compressedStream.Read(scanline, 0, this.bytesPerScanline); - - FilterType filterType = (FilterType)scanline[0]; - byte[] defilteredScanline; - - // TODO: It would be good if we can reduce the memory usage here. Each filter is creating a new row. - switch (filterType) - { - case FilterType.None: - - defilteredScanline = NoneFilter.Decode(scanline); - - break; - - case FilterType.Sub: - - defilteredScanline = SubFilter.Decode(scanline, this.bytesPerPixel); - - break; - - case FilterType.Up: - - defilteredScanline = UpFilter.Decode(scanline, previousScanline); - - break; - - case FilterType.Average: - - defilteredScanline = AverageFilter.Decode(scanline, previousScanline, this.bytesPerPixel); - - break; - - case FilterType.Paeth: - - defilteredScanline = PaethFilter.Decode(scanline, previousScanline, this.bytesPerPixel); - - break; - - default: - throw new ImageFormatException("Unknown filter type."); - } - - previousScanline = defilteredScanline; - this.ProcessDefilteredScanline(defilteredScanline, y, pixels); - } - } - - /// - /// Processes the de-filtered scanline filling the image pixel data - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The de-filtered scanline - /// The current image row. - /// The image pixels - private void ProcessDefilteredScanline(byte[] defilteredScanline, int row, PixelAccessor pixels) - where TColor : struct, IPackedPixel - where TPacked : struct - { - TColor color = default(TColor); - switch (this.PngColorType) - { - case PngColorType.Grayscale: - - for (int x = 0; x < this.header.Width; x++) - { - int offset = 1 + (x * this.bytesPerPixel); - - byte intensity = defilteredScanline[offset]; - color.PackFromBytes(intensity, intensity, intensity, 255); - pixels[x, row] = color; - } - - break; - - case PngColorType.GrayscaleWithAlpha: - - for (int x = 0; x < this.header.Width; x++) - { - int offset = 1 + (x * this.bytesPerPixel); - - byte intensity = defilteredScanline[offset]; - byte alpha = defilteredScanline[offset + this.bytesPerSample]; - - color.PackFromBytes(intensity, intensity, intensity, alpha); - pixels[x, row] = color; - } - - break; - - case PngColorType.Palette: - - byte[] newScanline = defilteredScanline.ToArrayByBitsLength(this.header.BitDepth); - - if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) - { - // If the alpha palette is not null and has one or more entries, this means, that the image contains an alpha - // channel and we should try to read it. - for (int x = 0; x < this.header.Width; x++) - { - int index = newScanline[x]; - int pixelOffset = index * 3; - - byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255; - - if (a > 0) - { - byte r = this.palette[pixelOffset]; - byte g = this.palette[pixelOffset + 1]; - byte b = this.palette[pixelOffset + 2]; - color.PackFromBytes(r, g, b, a); - } - - pixels[x, row] = color; - } - } - else - { - for (int x = 0; x < this.header.Width; x++) - { - int index = newScanline[x]; - int pixelOffset = index * 3; - - byte r = this.palette[pixelOffset]; - byte g = this.palette[pixelOffset + 1]; - byte b = this.palette[pixelOffset + 2]; - - color.PackFromBytes(r, g, b, 255); - pixels[x, row] = color; - } - } - - break; - - case PngColorType.Rgb: - - for (int x = 0; x < this.header.Width; x++) - { - int offset = 1 + (x * this.bytesPerPixel); - - byte r = defilteredScanline[offset]; - byte g = defilteredScanline[offset + this.bytesPerSample]; - byte b = defilteredScanline[offset + (2 * this.bytesPerSample)]; - - color.PackFromBytes(r, g, b, 255); - pixels[x, row] = color; - } - - break; - - case PngColorType.RgbWithAlpha: - - for (int x = 0; x < this.header.Width; x++) - { - int offset = 1 + (x * this.bytesPerPixel); - - byte r = defilteredScanline[offset]; - byte g = defilteredScanline[offset + this.bytesPerSample]; - byte b = defilteredScanline[offset + (2 * this.bytesPerSample)]; - byte a = defilteredScanline[offset + (3 * this.bytesPerSample)]; - - color.PackFromBytes(r, g, b, a); - pixels[x, row] = color; - } - - break; - } - } - - /// - /// Reads a text chunk containing image properties from the data. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to decode to. - /// The containing data. - private void ReadTextChunk(Image image, byte[] data) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int zeroIndex = 0; - - for (int i = 0; i < data.Length; i++) - { - if (data[i] == 0) - { - zeroIndex = i; - break; - } - } - - string name = Encoding.Unicode.GetString(data, 0, zeroIndex); - string value = Encoding.Unicode.GetString(data, zeroIndex + 1, data.Length - zeroIndex - 1); - - image.Properties.Add(new ImageProperty(name, value)); - } - - /// - /// Reads a header chunk from the data. - /// - /// The containing data. - private void ReadHeaderChunk(byte[] data) - { - this.header = new PngHeader(); - - data.ReverseBytes(0, 4); - data.ReverseBytes(4, 4); - - this.header.Width = BitConverter.ToInt32(data, 0); - this.header.Height = BitConverter.ToInt32(data, 4); - - this.header.BitDepth = data[8]; - this.header.ColorType = data[9]; - this.header.CompressionMethod = data[10]; - this.header.FilterMethod = data[11]; - this.header.InterlaceMethod = data[12]; - } - - /// - /// Validates the png header. - /// - /// - /// Thrown if the image does pass validation. - /// - private void ValidateHeader() - { - if (!ColorTypes.ContainsKey(this.header.ColorType)) - { - throw new NotSupportedException("Color type is not supported or not valid."); - } - - if (!ColorTypes[this.header.ColorType].Contains(this.header.BitDepth)) - { - throw new NotSupportedException("Bit depth is not supported or not valid."); - } - - if (this.header.FilterMethod != 0) - { - throw new NotSupportedException("The png specification only defines 0 as filter method."); - } - - if (this.header.InterlaceMethod != 0) - { - // TODO: Support interlacing - throw new NotSupportedException("Interlacing is not supported."); - } - - this.PngColorType = (PngColorType)this.header.ColorType; - } - - /// - /// Reads a chunk from the stream. - /// - /// - /// The . - /// - private PngChunk ReadChunk() - { - PngChunk chunk = new PngChunk(); - - if (this.ReadChunkLength(chunk) == 0) - { - return null; - } - - if (chunk.Length <= 0) - { - return null; - } - - this.ReadChunkType(chunk); - this.ReadChunkData(chunk); - this.ReadChunkCrc(chunk); - - return chunk; - } - - /// - /// Reads the cycle redundancy chunk from the data. - /// - /// The chunk. - /// - /// Thrown if the input stream is not valid or corrupt. - /// - private void ReadChunkCrc(PngChunk chunk) - { - int numBytes = this.currentStream.Read(this.crcBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - this.crcBuffer.ReverseBytes(); - - chunk.Crc = BitConverter.ToUInt32(this.crcBuffer, 0); - - Crc32 crc = new Crc32(); - crc.Update(this.chunkTypeBuffer); - crc.Update(chunk.Data); - - if (crc.Value != chunk.Crc) - { - throw new ImageFormatException("CRC Error. PNG Image chunk is corrupt!"); - } - } - - /// - /// Reads the chunk data from the stream. - /// - /// The chunk. - private void ReadChunkData(PngChunk chunk) - { - chunk.Data = new byte[chunk.Length]; - this.currentStream.Read(chunk.Data, 0, chunk.Length); - } - - /// - /// Identifies the chunk type from the chunk. - /// - /// The chunk. - /// - /// Thrown if the input stream is not valid. - /// - private void ReadChunkType(PngChunk chunk) - { - int numBytes = this.currentStream.Read(this.chunkTypeBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - this.chars[0] = (char)this.chunkTypeBuffer[0]; - this.chars[1] = (char)this.chunkTypeBuffer[1]; - this.chars[2] = (char)this.chunkTypeBuffer[2]; - this.chars[3] = (char)this.chunkTypeBuffer[3]; - - chunk.Type = new string(this.chars); - } - - /// - /// Calculates the length of the given chunk. - /// - /// he chunk. - /// - /// The representing the chunk length. - /// - /// - /// Thrown if the input stream is not valid. - /// - private int ReadChunkLength(PngChunk chunk) - { - int numBytes = this.currentStream.Read(this.chunkLengthBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - this.chunkLengthBuffer.ReverseBytes(); - - chunk.Length = BitConverter.ToInt32(this.chunkLengthBuffer, 0); - - return numBytes; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngEncoder.cs b/src/ImageSharp46/Formats/Png/PngEncoder.cs deleted file mode 100644 index af4fe95d6..000000000 --- a/src/ImageSharp46/Formats/Png/PngEncoder.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - - using ImageSharp.Quantizers; - - /// - /// Image encoder for writing image data to a stream in png format. - /// - public class PngEncoder : IImageEncoder - { - /// - /// Gets or sets the quality of output for images. - /// - public int Quality { get; set; } - - /// - /// Gets or sets the png color type - /// - public PngColorType PngColorType { get; set; } = PngColorType.RgbWithAlpha; - - /// - public string MimeType => "image/png"; - - /// - public string Extension => "png"; - - /// - /// Gets or sets the compression level 1-9. - /// Defaults to 6. - /// - public int CompressionLevel { get; set; } = 6; - - /// - /// Gets or sets the gamma value, that will be written - /// the the stream, when the property - /// is set to true. The default value is 2.2F. - /// - /// The gamma value of the image. - public float Gamma { get; set; } = 2.2F; - - /// - /// Gets or sets quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } = 0; - - /// - /// Gets or sets a value indicating whether this instance should write - /// gamma information to the stream. The default value is false. - /// - public bool WriteGamma { get; set; } - - /// - public bool IsSupportedFileExtension(string extension) - { - Guard.NotNullOrEmpty(extension, nameof(extension)); - - extension = extension.StartsWith(".") ? extension.Substring(1) : extension; - - return extension.Equals(this.Extension, StringComparison.OrdinalIgnoreCase); - } - - /// - public void Encode(Image image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - PngEncoderCore encoder = new PngEncoderCore - { - CompressionLevel = this.CompressionLevel, - Gamma = this.Gamma, - Quality = this.Quality, - PngColorType = this.PngColorType, - Quantizer = this.Quantizer, - WriteGamma = this.WriteGamma, - Threshold = this.Threshold - }; - - encoder.Encode(image, stream); - } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngEncoderCore.cs b/src/ImageSharp46/Formats/Png/PngEncoderCore.cs deleted file mode 100644 index a06e306f5..000000000 --- a/src/ImageSharp46/Formats/Png/PngEncoderCore.cs +++ /dev/null @@ -1,712 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Buffers; - using System.Collections.Generic; - using System.IO; - using System.Linq; - - using Quantizers; - - /// - /// Performs the png encoding operation. - /// TODO: Perf. There's lots of array parsing and copying going on here. This should be unmanaged. - /// - internal sealed class PngEncoderCore - { - /// - /// The maximum block size, defaults at 64k for uncompressed blocks. - /// - private const int MaxBlockSize = 65535; - - /// - /// Reusable buffer for writing chunk types. - /// - private readonly byte[] chunkTypeBuffer = new byte[4]; - - /// - /// Reusable buffer for writing chunk data. - /// - private readonly byte[] chunkDataBuffer = new byte[16]; - - - /// - /// Contains the raw pixel data from an indexed image. - /// - private byte[] palettePixelData; - - /// - /// The image width. - /// - private int width; - - /// - /// The image height. - /// - private int height; - - /// - /// The number of bits required to encode the colors in the png. - /// - private byte bitDepth; - - /// - /// The number of bytes per pixel. - /// - private int bytesPerPixel; - - /// - /// Gets or sets the quality of output for images. - /// - public int Quality { get; set; } - - /// - /// Gets or sets the png color type - /// - public PngColorType PngColorType { get; set; } - - /// - /// Gets or sets the compression level 1-9. - /// Defaults to 6. - /// - public int CompressionLevel { get; set; } = 6; - - /// - /// Gets or sets a value indicating whether this instance should write - /// gamma information to the stream. The default value is false. - /// - public bool WriteGamma { get; set; } - - /// - /// Gets or sets the gamma value, that will be written - /// the the stream, when the property - /// is set to true. The default value is 2.2F. - /// - /// The gamma value of the image. - public float Gamma { get; set; } = 2.2F; - - /// - /// Gets or sets the quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } - - /// - /// Encodes the image to the specified stream from the . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The to encode from. - /// The to encode the image data to. - public void Encode(ImageBase image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - this.width = image.Width; - this.height = image.Height; - - // Write the png header. - this.chunkDataBuffer[0] = 0x89; // Set the high bit. - this.chunkDataBuffer[1] = 0x50; // P - this.chunkDataBuffer[2] = 0x4E; // N - this.chunkDataBuffer[3] = 0x47; // G - this.chunkDataBuffer[4] = 0x0D; // Line ending CRLF - this.chunkDataBuffer[5] = 0x0A; // Line ending CRLF - this.chunkDataBuffer[6] = 0x1A; // EOF - this.chunkDataBuffer[7] = 0x0A; // LF - - stream.Write(this.chunkDataBuffer, 0, 8); - - // Ensure that quality can be set but has a fallback. - int quality = this.Quality > 0 ? this.Quality : image.Quality; - this.Quality = quality > 0 ? quality.Clamp(1, int.MaxValue) : int.MaxValue; - - // Set correct color type if the color count is 256 or less. - if (this.Quality <= 256) - { - this.PngColorType = PngColorType.Palette; - } - - if (this.PngColorType == PngColorType.Palette && this.Quality > 256) - { - this.Quality = 256; - } - - // Set correct bit depth. - this.bitDepth = this.Quality <= 256 - ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.Quality).Clamp(1, 8) - : (byte)8; - - // Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk - if (this.bitDepth == 3) - { - this.bitDepth = 4; - } - else if (this.bitDepth >= 5 || this.bitDepth <= 7) - { - this.bitDepth = 8; - } - - this.bytesPerPixel = this.CalculateBytesPerPixel(); - - PngHeader header = new PngHeader - { - Width = image.Width, - Height = image.Height, - ColorType = (byte)this.PngColorType, - BitDepth = this.bitDepth, - FilterMethod = 0, // None - CompressionMethod = 0, - InterlaceMethod = 0 - }; - - this.WriteHeaderChunk(stream, header); - - // Collect the indexed pixel data - if (this.PngColorType == PngColorType.Palette) - { - this.CollectIndexedBytes(image, stream, header); - } - - this.WritePhysicalChunk(stream, image); - this.WriteGammaChunk(stream); - this.WriteDataChunks(image, stream); - this.WriteEndChunk(stream); - stream.Flush(); - } - - /// - /// Writes an integer to the byte array. - /// - /// The containing image data. - /// The amount to offset by. - /// The value to write. - private static void WriteInteger(byte[] data, int offset, int value) - { - byte[] buffer = BitConverter.GetBytes(value); - - buffer.ReverseBytes(); - Buffer.BlockCopy(buffer, 0, data, offset, 4); - } - - /// - /// Writes an integer to the stream. - /// - /// The containing image data. - /// The value to write. - private static void WriteInteger(Stream stream, int value) - { - byte[] buffer = BitConverter.GetBytes(value); - - buffer.ReverseBytes(); - stream.Write(buffer, 0, 4); - } - - /// - /// Writes an unsigned integer to the stream. - /// - /// The containing image data. - /// The value to write. - private static void WriteInteger(Stream stream, uint value) - { - byte[] buffer = BitConverter.GetBytes(value); - - buffer.ReverseBytes(); - stream.Write(buffer, 0, 4); - } - - /// - /// Collects the indexed pixel data. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The containing image data. - /// The . - private void CollectIndexedBytes(ImageBase image, Stream stream, PngHeader header) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Quantize the image and get the pixels. - QuantizedImage quantized = this.WritePaletteChunk(stream, header, image); - this.palettePixelData = quantized.Pixels; - } - - /// - /// Collects a row of grayscale pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The row index. - /// The raw scanline. - private void CollectGrayscaleBytes(ImageBase image, int row, byte[] rawScanline) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Copy the pixels across from the image. - // Reuse the chunk type buffer. - using (PixelAccessor pixels = image.Lock()) - { - for (int x = 0; x < this.width; x++) - { - // Convert the color to YCbCr and store the luminance - // Optionally store the original color alpha. - int offset = x * this.bytesPerPixel; - pixels[x, row].ToBytes(this.chunkTypeBuffer, 0, ComponentOrder.XYZW); - byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2])); - - for (int i = 0; i < this.bytesPerPixel; i++) - { - if (i == 0) - { - rawScanline[offset] = luminance; - } - else - { - rawScanline[offset + i] = this.chunkTypeBuffer[3]; - } - } - } - } - } - - /// - /// Collects a row of true color pixel data. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The row index. - /// The raw scanline. - private void CollectColorBytes(ImageBase image, int row, byte[] rawScanline) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - int bpp = this.bytesPerPixel; - for (int x = 0; x < this.width; x++) - { - pixels[x, row].ToBytes(rawScanline, x * this.bytesPerPixel, bpp == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ); - } - } - } - - /// - /// Encodes the pixel data line by line. - /// Each scanline is encoded in the most optimal manner to improve compression. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The row. - /// The previous scanline. - /// The raw scanline. - /// The number of bytes per scanline. - /// The - private byte[] EncodePixelRow(ImageBase image, int row, byte[] previousScanline, byte[] rawScanline, int bytesPerScanline) - where TColor : struct, IPackedPixel - where TPacked : struct - { - switch (this.PngColorType) - { - case PngColorType.Palette: - Buffer.BlockCopy(this.palettePixelData, row * bytesPerScanline, rawScanline, 0, bytesPerScanline); - break; - case PngColorType.Grayscale: - case PngColorType.GrayscaleWithAlpha: - this.CollectGrayscaleBytes(image, row, rawScanline); - break; - default: - this.CollectColorBytes(image, row, rawScanline); - break; - } - - byte[] filteredScanline = this.GetOptimalFilteredScanline(rawScanline, previousScanline, bytesPerScanline, this.bytesPerPixel); - - return filteredScanline; - } - - /// - /// Applies all PNG filters to the given scanline and returns the filtered scanline that is deemed - /// to be most compressible, using lowest total variation as proxy for compressibility. - /// - /// The raw scanline - /// The previous scanline - /// The number of bytes per scanline - /// The number of bytes per pixel - /// The - private byte[] GetOptimalFilteredScanline(byte[] rawScanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel) - { - Tuple[] candidates; - - // Palette images don't compress well with adaptive filtering. - if (this.PngColorType == PngColorType.Palette) - { - candidates = new Tuple[1]; - - byte[] none = NoneFilter.Encode(rawScanline, bytesPerScanline); - candidates[0] = new Tuple(none, this.CalculateTotalVariation(none)); - } - else - { - candidates = new Tuple[4]; - - byte[] sub = SubFilter.Encode(rawScanline, bytesPerPixel, bytesPerScanline); - candidates[0] = new Tuple(sub, this.CalculateTotalVariation(sub)); - - byte[] up = UpFilter.Encode(rawScanline, bytesPerScanline, previousScanline); - candidates[1] = new Tuple(up, this.CalculateTotalVariation(up)); - - byte[] average = AverageFilter.Encode(rawScanline, previousScanline, bytesPerPixel, bytesPerScanline); - candidates[2] = new Tuple(average, this.CalculateTotalVariation(average)); - - byte[] paeth = PaethFilter.Encode(rawScanline, previousScanline, bytesPerPixel, bytesPerScanline); - candidates[3] = new Tuple(paeth, this.CalculateTotalVariation(paeth)); - } - - int lowestTotalVariation = int.MaxValue; - int lowestTotalVariationIndex = 0; - - for (int i = 0; i < candidates.Length; i++) - { - if (candidates[i].Item2 < lowestTotalVariation) - { - lowestTotalVariationIndex = i; - lowestTotalVariation = candidates[i].Item2; - } - } - - return candidates[lowestTotalVariationIndex].Item1; - } - - /// - /// Calculates the total variation of given byte array. Total variation is the sum of the absolute values of - /// neighbor differences. - /// - /// The scanline bytes - /// The - private int CalculateTotalVariation(byte[] input) - { - int totalVariation = 0; - - for (int i = 1; i < input.Length; i++) - { - totalVariation += Math.Abs(input[i] - input[i - 1]); - } - - return totalVariation; - } - - /// - /// Calculates the correct number of bytes per pixel for the given color type. - /// - /// The - private int CalculateBytesPerPixel() - { - switch (this.PngColorType) - { - case PngColorType.Grayscale: - return 1; - - case PngColorType.GrayscaleWithAlpha: - return 2; - - case PngColorType.Palette: - return 1; - - case PngColorType.Rgb: - return 3; - - // PngColorType.RgbWithAlpha - // TODO: Maybe figure out a way to detect if there are any transparent - // pixels and encode RGB if none. - default: - return 4; - } - } - - /// - /// Writes the header chunk to the stream. - /// - /// The containing image data. - /// The . - private void WriteHeaderChunk(Stream stream, PngHeader header) - { - WriteInteger(this.chunkDataBuffer, 0, header.Width); - WriteInteger(this.chunkDataBuffer, 4, header.Height); - - this.chunkDataBuffer[8] = header.BitDepth; - this.chunkDataBuffer[9] = header.ColorType; - this.chunkDataBuffer[10] = header.CompressionMethod; - this.chunkDataBuffer[11] = header.FilterMethod; - this.chunkDataBuffer[12] = header.InterlaceMethod; - - this.WriteChunk(stream, PngChunkTypes.Header, this.chunkDataBuffer, 0, 13); - } - - /// - /// Writes the palette chunk to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing image data. - /// The . - /// The image to encode. - /// The - private QuantizedImage WritePaletteChunk(Stream stream, PngHeader header, ImageBase image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (this.Quality > 256) - { - return null; - } - - if (this.Quantizer == null) - { - this.Quantizer = new WuQuantizer(); - } - - // Quantize the image returning a palette. This boxing is icky. - QuantizedImage quantized = ((IQuantizer)this.Quantizer).Quantize(image, this.Quality); - - // Grab the palette and write it to the stream. - TColor[] palette = quantized.Palette; - int pixelCount = palette.Length; - List transparentPixels = new List(); - - // Get max colors for bit depth. - int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3; - byte[] colorTable = ArrayPool.Shared.Rent(colorTableLength); - byte[] bytes = ArrayPool.Shared.Rent(4); - - try - { - for (int i = 0; i < pixelCount; i++) - { - int offset = i * 3; - palette[i].ToBytes(bytes, 0, ComponentOrder.XYZW); - - int alpha = bytes[3]; - - // Premultiply the color. This helps prevent banding. - // TODO: Vector? - if (alpha < 255 && alpha > this.Threshold) - { - bytes[0] = (byte)(bytes[0] * alpha).Clamp(0, 255); - bytes[1] = (byte)(bytes[1] * alpha).Clamp(0, 255); - bytes[2] = (byte)(bytes[2] * alpha).Clamp(0, 255); - } - - colorTable[offset] = bytes[0]; - colorTable[offset + 1] = bytes[1]; - colorTable[offset + 2] = bytes[2]; - - if (alpha <= this.Threshold) - { - transparentPixels.Add((byte)offset); - } - } - - this.WriteChunk(stream, PngChunkTypes.Palette, colorTable, 0, colorTableLength); - } - finally - { - ArrayPool.Shared.Return(colorTable); - ArrayPool.Shared.Return(bytes); - } - - // Write the transparency data - if (transparentPixels.Any()) - { - this.WriteChunk(stream, PngChunkTypes.PaletteAlpha, transparentPixels.ToArray()); - } - - return quantized; - } - - /// - /// Writes the physical dimension information to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The containing image data. - /// The image base. - private void WritePhysicalChunk(Stream stream, ImageBase imageBase) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Image image = imageBase as Image; - if (image != null && image.HorizontalResolution > 0 && image.VerticalResolution > 0) - { - // 39.3700787 = inches in a meter. - int dpmX = (int)Math.Round(image.HorizontalResolution * 39.3700787D); - int dpmY = (int)Math.Round(image.VerticalResolution * 39.3700787D); - - WriteInteger(this.chunkDataBuffer, 0, dpmX); - WriteInteger(this.chunkDataBuffer, 4, dpmY); - - this.chunkDataBuffer[8] = 1; - - this.WriteChunk(stream, PngChunkTypes.Physical, this.chunkDataBuffer, 0, 9); - } - } - - /// - /// Writes the gamma information to the stream. - /// - /// The containing image data. - private void WriteGammaChunk(Stream stream) - { - if (this.WriteGamma) - { - int gammaValue = (int)(this.Gamma * 100000F); - - byte[] size = BitConverter.GetBytes(gammaValue); - - this.chunkDataBuffer[0] = size[3]; - this.chunkDataBuffer[1] = size[2]; - this.chunkDataBuffer[2] = size[1]; - this.chunkDataBuffer[3] = size[0]; - - this.WriteChunk(stream, PngChunkTypes.Gamma, this.chunkDataBuffer, 0, 4); - } - } - - /// - /// Writes the pixel information to the stream. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to encode. - /// The stream. - private void WriteDataChunks(ImageBase image, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int bytesPerScanline = this.width * this.bytesPerPixel; - byte[] previousScanline = ArrayPool.Shared.Rent(bytesPerScanline); - byte[] rawScanline = ArrayPool.Shared.Rent(bytesPerScanline); - - byte[] buffer; - int bufferLength; - MemoryStream memoryStream = null; - try - { - memoryStream = new MemoryStream(); - using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel)) - { - for (int y = 0; y < this.height; y++) - { - byte[] data = this.EncodePixelRow(image, y, previousScanline, rawScanline, bytesPerScanline); - deflateStream.Write(data, 0, data.Length); - deflateStream.Flush(); - - // Do a bit of shuffling; - byte[] tmp = rawScanline; - rawScanline = previousScanline; - previousScanline = tmp; - } - - bufferLength = (int)memoryStream.Length; - buffer = memoryStream.ToArray(); - } - } - finally - { - ArrayPool.Shared.Return(previousScanline); - ArrayPool.Shared.Return(rawScanline); - memoryStream?.Dispose(); - } - - // Store the chunks in repeated 64k blocks. - // This reduces the memory load for decoding the image for many decoders. - int numChunks = bufferLength / MaxBlockSize; - - if (bufferLength % MaxBlockSize != 0) - { - numChunks++; - } - - for (int i = 0; i < numChunks; i++) - { - int length = bufferLength - (i * MaxBlockSize); - - if (length > MaxBlockSize) - { - length = MaxBlockSize; - } - - this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length); - } - } - - /// - /// Writes the chunk end to the stream. - /// - /// The containing image data. - private void WriteEndChunk(Stream stream) - { - this.WriteChunk(stream, PngChunkTypes.End, null); - } - - /// - /// Writes a chunk to the stream. - /// - /// The to write to. - /// The type of chunk to write. - /// The containing data. - private void WriteChunk(Stream stream, string type, byte[] data) - { - this.WriteChunk(stream, type, data, 0, data?.Length ?? 0); - } - - /// - /// Writes a chunk of a specified length to the stream at the given offset. - /// - /// The to write to. - /// The type of chunk to write. - /// The containing data. - /// The position to offset the data at. - /// The of the data to write. - private void WriteChunk(Stream stream, string type, byte[] data, int offset, int length) - { - // Chunk length - WriteInteger(stream, length); - - // Chunk type - this.chunkTypeBuffer[0] = (byte)type[0]; - this.chunkTypeBuffer[1] = (byte)type[1]; - this.chunkTypeBuffer[2] = (byte)type[2]; - this.chunkTypeBuffer[3] = (byte)type[3]; - - stream.Write(this.chunkTypeBuffer, 0, 4); - - Crc32 crc32 = new Crc32(); - crc32.Update(this.chunkTypeBuffer); - - // Chunk data - if (data != null) - { - stream.Write(data, offset, length); - crc32.Update(data, offset, length); - } - - WriteInteger(stream, (uint)crc32.Value); - } - } -} diff --git a/src/ImageSharp46/Formats/Png/PngFormat.cs b/src/ImageSharp46/Formats/Png/PngFormat.cs deleted file mode 100644 index 230ba8b40..000000000 --- a/src/ImageSharp46/Formats/Png/PngFormat.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Encapsulates the means to encode and decode png images. - /// - public class PngFormat : IImageFormat - { - /// - public IImageDecoder Decoder => new PngDecoder(); - - /// - public IImageEncoder Encoder => new PngEncoder(); - } -} diff --git a/src/ImageSharp46/Formats/Png/PngHeader.cs b/src/ImageSharp46/Formats/Png/PngHeader.cs deleted file mode 100644 index 3121969b6..000000000 --- a/src/ImageSharp46/Formats/Png/PngHeader.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Represents the png header chunk. - /// - public sealed class PngHeader - { - /// - /// Gets or sets the dimension in x-direction of the image in pixels. - /// - public int Width { get; set; } - - /// - /// Gets or sets the dimension in y-direction of the image in pixels. - /// - public int Height { get; set; } - - /// - /// Gets or sets the bit depth. - /// Bit depth is a single-byte integer giving the number of bits per sample - /// or per palette index (not per pixel). Valid values are 1, 2, 4, 8, and 16, - /// although not all values are allowed for all color types. - /// - public byte BitDepth { get; set; } - - /// - /// Gets or sets the color type. - /// Color type is a integer that describes the interpretation of the - /// image data. Color type codes represent sums of the following values: - /// 1 (palette used), 2 (color used), and 4 (alpha channel used). - /// - public byte ColorType { get; set; } - - /// - /// Gets or sets the compression method. - /// Indicates the method used to compress the image data. At present, - /// only compression method 0 (deflate/inflate compression with a sliding - /// window of at most 32768 bytes) is defined. - /// - public byte CompressionMethod { get; set; } - - /// - /// Gets or sets the preprocessing method. - /// Indicates the preprocessing method applied to the image - /// data before compression. At present, only filter method 0 - /// (adaptive filtering with five basic filter types) is defined. - /// - public byte FilterMethod { get; set; } - - /// - /// Gets or sets the transmission order. - /// Indicates the transmission order of the image data. - /// Two values are currently defined: 0 (no interlace) or 1 (Adam7 interlace). - /// - public byte InterlaceMethod { get; set; } - } -} diff --git a/src/ImageSharp46/Formats/Png/README.md b/src/ImageSharp46/Formats/Png/README.md deleted file mode 100644 index 8ade37956..000000000 --- a/src/ImageSharp46/Formats/Png/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Encoder/Decoder adapted from: - -https://github.com/yufeih/Nine.Imaging/ -https://imagetools.codeplex.com/ -https://github.com/leonbloy/pngcs - diff --git a/src/ImageSharp46/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp46/Formats/Png/Zlib/Adler32.cs deleted file mode 100644 index 5f92cc9e0..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/Adler32.cs +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// Computes Adler32 checksum for a stream of data. An Adler32 - /// checksum is not as reliable as a CRC32 checksum, but a lot faster to - /// compute. - /// - /// - /// The specification for Adler32 may be found in RFC 1950. - /// ZLIB Compressed Data Format Specification version 3.3) - /// - /// - /// From that document: - /// - /// "ADLER32 (Adler-32 checksum) - /// This contains a checksum value of the uncompressed data - /// (excluding any dictionary data) computed according to Adler-32 - /// algorithm. This algorithm is a 32-bit extension and improvement - /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - /// standard. - /// - /// Adler-32 is composed of two sums accumulated per byte: s1 is - /// the sum of all bytes, s2 is the sum of all s1 values. Both sums - /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The - /// Adler-32 checksum is stored as s2*65536 + s1 in most- - /// significant-byte first (network) order." - /// - /// "8.2. The Adler-32 algorithm - /// - /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet - /// still provides an extremely low probability of undetected errors. - /// - /// The modulo on unsigned long accumulators can be delayed for 5552 - /// bytes, so the modulo operation time is negligible. If the bytes - /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - /// and order sensitive, unlike the first sum, which is just a - /// checksum. That 65521 is prime is important to avoid a possible - /// large class of two-byte errors that leave the check unchanged. - /// (The Fletcher checksum uses 255, which is not prime and which also - /// makes the Fletcher check insensitive to single byte changes 0 - - /// 255.) - /// - /// The sum s1 is initialized to 1 instead of zero to make the length - /// of the sequence part of s2, so that the length does not have to be - /// checked separately. (Any sequence of zeroes has a Fletcher - /// checksum of zero.)" - /// - /// - /// - internal sealed class Adler32 : IChecksum - { - /// - /// largest prime smaller than 65536 - /// - private const uint Base = 65521; - - /// - /// The checksum calculated to far. - /// - private uint checksum; - - /// - /// Initializes a new instance of the class. - /// The checksum starts off with a value of 1. - /// - public Adler32() - { - this.Reset(); - } - - /// - public long Value => this.checksum; - - /// - public void Reset() - { - this.checksum = 1; - } - - /// - /// Updates the checksum with a byte value. - /// - /// - /// The data value to add. The high byte of the int is ignored. - /// - public void Update(int value) - { - // We could make a length 1 byte array and call update again, but I - // would rather not have that overhead - uint s1 = this.checksum & 0xFFFF; - uint s2 = this.checksum >> 16; - - s1 = (s1 + ((uint)value & 0xFF)) % Base; - s2 = (s1 + s2) % Base; - - this.checksum = (s2 << 16) + s1; - } - - /// - public void Update(byte[] buffer) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - this.Update(buffer, 0, buffer.Length); - } - - /// - public void Update(byte[] buffer, int offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(offset), "cannot be negative"); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "cannot be negative"); - } - - if (offset >= buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset), "not a valid index into buffer"); - } - - if (offset + count > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(count), "exceeds buffer size"); - } - - // (By Per Bothner) - uint s1 = this.checksum & 0xFFFF; - uint s2 = this.checksum >> 16; - - while (count > 0) - { - // We can defer the modulo operation: - // s1 maximally grows from 65521 to 65521 + 255 * 3800 - // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 - int n = 3800; - if (n > count) - { - n = count; - } - - count -= n; - while (--n >= 0) - { - s1 = s1 + (uint)(buffer[offset++] & 0xff); - s2 = s2 + s1; - } - - s1 %= Base; - s2 %= Base; - } - - this.checksum = (s2 << 16) | s1; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Zlib/Crc32.cs b/src/ImageSharp46/Formats/Png/Zlib/Crc32.cs deleted file mode 100644 index d940112a8..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/Crc32.cs +++ /dev/null @@ -1,180 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - - /// - /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - /// - /// - /// - /// Polynomials over GF(2) are represented in binary, one bit per coefficient, - /// with the lowest powers in the most significant bit. Then adding polynomials - /// is just exclusive-or, and multiplying a polynomial by x is a right shift by - /// one. If we call the above polynomial p, and represent a byte as the - /// polynomial q, also with the lowest power in the most significant bit (so the - /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - /// where a mod b means the remainder after dividing a by b. - /// - /// - /// This calculation is done using the shift-register method of multiplying and - /// taking the remainder. The register is initialized to zero, and for each - /// incoming bit, x^32 is added mod p to the register if the bit is a one (where - /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - /// x (which is shifting right by one and adding x^32 mod p if the bit shifted - /// out is a one). We start with the highest power (least significant bit) of - /// q and repeat for all eight bits of q. - /// - /// - /// The table is simply the CRC of all possible eight bit values. This is all - /// the information needed to generate CRC's on data a byte at a time for all - /// combinations of CRC register values and incoming bytes. - /// - /// - internal sealed class Crc32 : IChecksum - { - /// - /// The cycle redundancy check seed - /// - private const uint CrcSeed = 0xFFFFFFFF; - - /// - /// The table of all possible eight bit values for fast lookup. - /// - private static readonly uint[] CrcTable = - { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, - 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, - 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, - 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, - 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, - 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, - 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, - 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, - 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, - 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, - 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, - 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, - 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, - 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, - 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, - 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, - 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, - 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, - 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, - 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, - 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, - 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, - 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, - 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, - 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, - 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, - 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, - 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, - 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, - 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, - 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, - 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, - 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, - 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, - 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, - 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, - 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, - 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, - 0x2D02EF8D - }; - - /// - /// The data checksum so far. - /// - private uint crc; - - /// - public long Value - { - get - { - return this.crc; - } - - set - { - this.crc = (uint)value; - } - } - - /// - public void Reset() - { - this.crc = 0; - } - - /// - /// Updates the checksum with the given value. - /// - /// The byte is taken as the lower 8 bits of value. - public void Update(int value) - { - this.crc ^= CrcSeed; - this.crc = CrcTable[(this.crc ^ value) & 0xFF] ^ (this.crc >> 8); - this.crc ^= CrcSeed; - } - - /// - public void Update(byte[] buffer) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - this.Update(buffer, 0, buffer.Length); - } - - /// - public void Update(byte[] buffer, int offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "Count cannot be less than zero"); - } - - if (offset < 0 || offset + count > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - - this.crc ^= CrcSeed; - - while (--count >= 0) - { - this.crc = CrcTable[(this.crc ^ buffer[offset++]) & 0xFF] ^ (this.crc >> 8); - } - - this.crc ^= CrcSeed; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Zlib/IChecksum.cs b/src/ImageSharp46/Formats/Png/Zlib/IChecksum.cs deleted file mode 100644 index 935cdf953..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/IChecksum.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - /// - /// Interface to compute a data checksum used by checked input/output streams. - /// A data checksum can be updated by one byte or with a byte array. After each - /// update the value of the current checksum can be returned by calling - /// Value. The complete checksum object can also be reset - /// so it can be used again with new data. - /// - public interface IChecksum - { - /// - /// Gets the data checksum computed so far. - /// - long Value - { - get; - } - - /// - /// Resets the data checksum as if no update was ever called. - /// - void Reset(); - - /// - /// Adds one byte to the data checksum. - /// - /// - /// The data value to add. The high byte of the integer is ignored. - /// - void Update(int value); - - /// - /// Updates the data checksum with the bytes taken from the array. - /// - /// - /// buffer an array of bytes - /// - void Update(byte[] buffer); - - /// - /// Adds the byte array to the data checksum. - /// - /// - /// The buffer which contains the data - /// - /// - /// The offset in the buffer where the data starts - /// - /// - /// the number of data bytes to add. - /// - void Update(byte[] buffer, int offset, int count); - } -} diff --git a/src/ImageSharp46/Formats/Png/Zlib/README.md b/src/ImageSharp46/Formats/Png/Zlib/README.md deleted file mode 100644 index c297a91d5..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/README.md +++ /dev/null @@ -1,2 +0,0 @@ -Adler32.cs and Crc32.cs have been copied from -https://github.com/ygrenier/SharpZipLib.Portable diff --git a/src/ImageSharp46/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageSharp46/Formats/Png/Zlib/ZlibDeflateStream.cs deleted file mode 100644 index 2deb7dcf0..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/ZlibDeflateStream.cs +++ /dev/null @@ -1,210 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - using System.IO.Compression; - - /// - /// Provides methods and properties for compressing streams by using the Zlib Deflate algorithm. - /// - internal sealed class ZlibDeflateStream : Stream - { - /// - /// The raw stream containing the uncompressed image data. - /// - private readonly Stream rawStream; - - /// - /// Computes the checksum for the data stream. - /// - private readonly Adler32 adler32 = new Adler32(); - - /// - /// A value indicating whether this instance of the given entity has been disposed. - /// - /// if this instance has been disposed; otherwise, . - /// - /// If the entity is disposed, it must not be disposed a second - /// time. The isDisposed field is set the first time the entity - /// is disposed. If the isDisposed field is true, then the Dispose() - /// method will not dispose again. This help not to prolong the entity's - /// life in the Garbage Collector. - /// - private bool isDisposed; - - /// - /// The stream responsible for compressing the input stream. - /// - private DeflateStream deflateStream; - - /// - /// Initializes a new instance of the class. - /// - /// The stream to compress. - /// The compression level. - public ZlibDeflateStream(Stream stream, int compressionLevel) - { - this.rawStream = stream; - - // Write the zlib header : http://tools.ietf.org/html/rfc1950 - // CMF(Compression Method and flags) - // This byte is divided into a 4 - bit compression method and a - // 4-bit information field depending on the compression method. - // bits 0 to 3 CM Compression method - // bits 4 to 7 CINFO Compression info - // - // 0 1 - // +---+---+ - // |CMF|FLG| - // +---+---+ - int cmf = 0x78; - int flg = 218; - - // http://stackoverflow.com/a/2331025/277304 - if (compressionLevel >= 5 && compressionLevel <= 6) - { - flg = 156; - } - else if (compressionLevel >= 3 && compressionLevel <= 4) - { - flg = 94; - } - else if (compressionLevel <= 2) - { - flg = 1; - } - - // Just in case - flg -= ((cmf * 256) + flg) % 31; - - if (flg < 0) - { - flg += 31; - } - - this.rawStream.WriteByte((byte)cmf); - this.rawStream.WriteByte((byte)flg); - - // Initialize the deflate Stream. - CompressionLevel level = CompressionLevel.Optimal; - - if (compressionLevel >= 1 && compressionLevel <= 5) - { - level = CompressionLevel.Fastest; - } - else if (compressionLevel == 0) - { - level = CompressionLevel.NoCompression; - } - - this.deflateStream = new DeflateStream(this.rawStream, level, true); - } - - /// - public override bool CanRead => false; - - /// - public override bool CanSeek => false; - - /// - public override bool CanWrite => true; - - /// - public override long Length - { - get - { - throw new NotSupportedException(); - } - } - - /// - public override long Position - { - get - { - throw new NotSupportedException(); - } - - set - { - throw new NotSupportedException(); - } - } - - /// - public override void Flush() - { - this.deflateStream?.Flush(); - } - - /// - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - /// - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// - public override void Write(byte[] buffer, int offset, int count) - { - this.deflateStream.Write(buffer, offset, count); - this.adler32.Update(buffer, offset, count); - } - - /// - protected override void Dispose(bool disposing) - { - if (this.isDisposed) - { - return; - } - - if (disposing) - { - // dispose managed resources - if (this.deflateStream != null) - { - this.deflateStream.Dispose(); - this.deflateStream = null; - } - else - { - // Hack: empty input? - this.rawStream.WriteByte(3); - this.rawStream.WriteByte(0); - } - - // Add the crc - uint crc = (uint)this.adler32.Value; - this.rawStream.WriteByte((byte)((crc >> 24) & 0xFF)); - this.rawStream.WriteByte((byte)((crc >> 16) & 0xFF)); - this.rawStream.WriteByte((byte)((crc >> 8) & 0xFF)); - this.rawStream.WriteByte((byte)(crc & 0xFF)); - } - - base.Dispose(disposing); - - // Call the appropriate methods to clean up - // unmanaged resources here. - // Note disposing is done. - this.isDisposed = true; - } - } -} diff --git a/src/ImageSharp46/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp46/Formats/Png/Zlib/ZlibInflateStream.cs deleted file mode 100644 index 977a4a167..000000000 --- a/src/ImageSharp46/Formats/Png/Zlib/ZlibInflateStream.cs +++ /dev/null @@ -1,214 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.IO; - using System.IO.Compression; - - /// - /// Provides methods and properties for decompressing streams by using the Zlib Deflate algorithm. - /// - internal sealed class ZlibInflateStream : Stream - { - /// - /// The raw stream containing the uncompressed image data. - /// - private readonly Stream rawStream; - - /// - /// A value indicating whether this instance of the given entity has been disposed. - /// - /// if this instance has been disposed; otherwise, . - /// - /// If the entity is disposed, it must not be disposed a second - /// time. The isDisposed field is set the first time the entity - /// is disposed. If the isDisposed field is true, then the Dispose() - /// method will not dispose again. This help not to prolong the entity's - /// life in the Garbage Collector. - /// - private bool isDisposed; - - /// - /// The read crc data. - /// - private byte[] crcread; - - /// - /// The stream responsible for decompressing the input stream. - /// - private DeflateStream deflateStream; - - /// - /// Initializes a new instance of the class. - /// - /// The stream. - /// - /// Thrown if the compression method is incorrect. - /// - public ZlibInflateStream(Stream stream) - { - // The DICT dictionary identifier identifying the used dictionary. - - // The preset dictionary. - bool fdict; - this.rawStream = stream; - - // Read the zlib header : http://tools.ietf.org/html/rfc1950 - // CMF(Compression Method and flags) - // This byte is divided into a 4 - bit compression method and a - // 4-bit information field depending on the compression method. - // bits 0 to 3 CM Compression method - // bits 4 to 7 CINFO Compression info - // - // 0 1 - // +---+---+ - // |CMF|FLG| - // +---+---+ - int cmf = this.rawStream.ReadByte(); - int flag = this.rawStream.ReadByte(); - if (cmf == -1 || flag == -1) - { - return; - } - - if ((cmf & 0x0f) != 8) - { - throw new Exception($"Bad compression method for ZLIB header: cmf={cmf}"); - } - - // CINFO is the base-2 logarithm of the LZ77 window size, minus eight. - // int cinfo = ((cmf & (0xf0)) >> 8); - fdict = (flag & 32) != 0; - - if (fdict) - { - // The DICT dictionary identifier identifying the used dictionary. - byte[] dictId = new byte[4]; - - for (int i = 0; i < 4; i++) - { - // We consume but don't use this. - dictId[i] = (byte)this.rawStream.ReadByte(); - } - } - - // Initialize the deflate Stream. - this.deflateStream = new DeflateStream(this.rawStream, CompressionMode.Decompress, true); - } - - /// - public override bool CanRead => true; - - /// - public override bool CanSeek => false; - - /// - public override bool CanWrite => false; - - /// - public override long Length - { - get - { - throw new NotSupportedException(); - } - } - - /// - public override long Position - { - get - { - throw new NotSupportedException(); - } - - set - { - throw new NotSupportedException(); - } - } - - /// - public override void Flush() - { - this.deflateStream?.Flush(); - } - - /// - public override int Read(byte[] buffer, int offset, int count) - { - // We dont't check CRC on reading - int read = this.deflateStream.Read(buffer, offset, count); - if (read < 1 && this.crcread == null) - { - // The deflater has ended. We try to read the next 4 bytes from raw stream (crc) - this.crcread = new byte[4]; - for (int i = 0; i < 4; i++) - { - // we dont really check/use this - this.crcread[i] = (byte)this.rawStream.ReadByte(); - } - } - - return read; - } - - /// - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - /// - protected override void Dispose(bool disposing) - { - if (this.isDisposed) - { - return; - } - - if (disposing) - { - // dispose managed resources - if (this.deflateStream != null) - { - this.deflateStream.Dispose(); - this.deflateStream = null; - - if (this.crcread == null) - { - // Consume the trailing 4 bytes - this.crcread = new byte[4]; - for (int i = 0; i < 4; i++) - { - this.crcread[i] = (byte)this.rawStream.ReadByte(); - } - } - } - } - - base.Dispose(disposing); - - // Call the appropriate methods to clean up - // unmanaged resources here. - // Note disposing is done. - this.isDisposed = true; - } - } -} diff --git a/src/ImageSharp46/IO/BigEndianBitConverter.cs b/src/ImageSharp46/IO/BigEndianBitConverter.cs deleted file mode 100644 index 084102728..000000000 --- a/src/ImageSharp46/IO/BigEndianBitConverter.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - /// - /// Implementation of EndianBitConverter which converts to/from big-endian - /// byte arrays. - /// - /// Adapted from Miscellaneous Utility Library - /// This product includes software developed by Jon Skeet and Marc Gravell. Contact , or see - /// . - /// - /// - internal sealed class BigEndianBitConverter : EndianBitConverter - { - /// - public override Endianness Endianness => Endianness.BigEndian; - - /// - public override bool IsLittleEndian() => false; - - /// - protected internal override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index) - { - int endOffset = index + bytes - 1; - for (int i = 0; i < bytes; i++) - { - buffer[endOffset - i] = unchecked((byte)(value & 0xff)); - value = value >> 8; - } - } - - /// - protected internal override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert) - { - long ret = 0; - for (int i = 0; i < bytesToConvert; i++) - { - ret = unchecked((ret << 8) | buffer[startIndex + i]); - } - - return ret; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/IO/EndianBinaryReader.cs b/src/ImageSharp46/IO/EndianBinaryReader.cs deleted file mode 100644 index 3b12401b6..000000000 --- a/src/ImageSharp46/IO/EndianBinaryReader.cs +++ /dev/null @@ -1,615 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - using System; - using System.IO; - using System.Text; - - /// - /// Equivalent of , but with either endianness, depending on - /// the EndianBitConverter it is constructed with. No data is buffered in the - /// reader; the client may seek within the stream at will. - /// - internal class EndianBinaryReader : IDisposable - { - /// - /// Decoder to use for string conversions. - /// - private readonly Decoder decoder; - - /// - /// Buffer used for temporary storage before conversion into primitives - /// - private readonly byte[] buffer = new byte[16]; - - /// - /// Buffer used for temporary storage when reading a single character - /// - private readonly char[] charBuffer = new char[1]; - - /// - /// Minimum number of bytes used to encode a character - /// - private readonly int minBytesPerChar; - - /// - /// Whether or not this reader has been disposed yet. - /// - private bool disposed; - - /// - /// Equivalent of System.IO.BinaryWriter, but with either endianness, depending on - /// the EndianBitConverter it is constructed with. - /// - /// Converter to use when reading data - /// Stream to read data from - public EndianBinaryReader(EndianBitConverter bitConverter, Stream stream) - : this(bitConverter, stream, Encoding.UTF8) - { - } - - /// - /// Constructs a new binary reader with the given bit converter, reading - /// to the given stream, using the given encoding. - /// - /// Converter to use when reading data - /// Stream to read data from - /// Encoding to use when reading character data - public EndianBinaryReader(EndianBitConverter bitConverter, Stream stream, Encoding encoding) - { - // TODO: Use Guard - if (bitConverter == null) - { - throw new ArgumentNullException("bitConverter"); - } - - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - if (encoding == null) - { - throw new ArgumentNullException("encoding"); - } - - if (!stream.CanRead) - { - throw new ArgumentException("Stream isn't writable", "stream"); - } - - this.BaseStream = stream; - this.BitConverter = bitConverter; - this.Encoding = encoding; - this.decoder = encoding.GetDecoder(); - this.minBytesPerChar = 1; - - if (encoding is UnicodeEncoding) - { - this.minBytesPerChar = 2; - } - } - - /// - /// Gets the bit converter used to read values from the stream. - /// - public EndianBitConverter BitConverter { get; } - - /// - /// Gets the encoding used to read strings - /// - public Encoding Encoding { get; } - - /// - /// Gets the underlying stream of the EndianBinaryReader. - /// - public Stream BaseStream { get; } - - /// - /// Closes the reader, including the underlying stream. - /// - public void Close() - { - this.Dispose(); - } - - /// - /// Seeks within the stream. - /// - /// Offset to seek to. - /// Origin of seek operation. - public void Seek(int offset, SeekOrigin origin) - { - this.CheckDisposed(); - this.BaseStream.Seek(offset, origin); - } - - /// - /// Reads a single byte from the stream. - /// - /// The byte read - public byte ReadByte() - { - this.ReadInternal(this.buffer, 1); - return this.buffer[0]; - } - - /// - /// Reads a single signed byte from the stream. - /// - /// The byte read - public sbyte ReadSByte() - { - this.ReadInternal(this.buffer, 1); - return unchecked((sbyte)this.buffer[0]); - } - - /// - /// Reads a boolean from the stream. 1 byte is read. - /// - /// The boolean read - public bool ReadBoolean() - { - this.ReadInternal(this.buffer, 1); - return this.BitConverter.ToBoolean(this.buffer, 0); - } - - /// - /// Reads a 16-bit signed integer from the stream, using the bit converter - /// for this reader. 2 bytes are read. - /// - /// The 16-bit integer read - public short ReadInt16() - { - this.ReadInternal(this.buffer, 2); - return this.BitConverter.ToInt16(this.buffer, 0); - } - - /// - /// Reads a 32-bit signed integer from the stream, using the bit converter - /// for this reader. 4 bytes are read. - /// - /// The 32-bit integer read - public int ReadInt32() - { - this.ReadInternal(this.buffer, 4); - return this.BitConverter.ToInt32(this.buffer, 0); - } - - /// - /// Reads a 64-bit signed integer from the stream, using the bit converter - /// for this reader. 8 bytes are read. - /// - /// The 64-bit integer read - public long ReadInt64() - { - this.ReadInternal(this.buffer, 8); - return this.BitConverter.ToInt64(this.buffer, 0); - } - - /// - /// Reads a 16-bit unsigned integer from the stream, using the bit converter - /// for this reader. 2 bytes are read. - /// - /// The 16-bit unsigned integer read - public ushort ReadUInt16() - { - this.ReadInternal(this.buffer, 2); - return this.BitConverter.ToUInt16(this.buffer, 0); - } - - /// - /// Reads a 32-bit unsigned integer from the stream, using the bit converter - /// for this reader. 4 bytes are read. - /// - /// The 32-bit unsigned integer read - public uint ReadUInt32() - { - this.ReadInternal(this.buffer, 4); - return this.BitConverter.ToUInt32(this.buffer, 0); - } - - /// - /// Reads a 64-bit unsigned integer from the stream, using the bit converter - /// for this reader. 8 bytes are read. - /// - /// The 64-bit unsigned integer read - public ulong ReadUInt64() - { - this.ReadInternal(this.buffer, 8); - return this.BitConverter.ToUInt64(this.buffer, 0); - } - - /// - /// Reads a single-precision floating-point value from the stream, using the bit converter - /// for this reader. 4 bytes are read. - /// - /// The floating point value read - public float ReadSingle() - { - this.ReadInternal(this.buffer, 4); - return this.BitConverter.ToSingle(this.buffer, 0); - } - - /// - /// Reads a double-precision floating-point value from the stream, using the bit converter - /// for this reader. 8 bytes are read. - /// - /// The floating point value read - public double ReadDouble() - { - this.ReadInternal(this.buffer, 8); - return this.BitConverter.ToDouble(this.buffer, 0); - } - - /// - /// Reads a decimal value from the stream, using the bit converter - /// for this reader. 16 bytes are read. - /// - /// The decimal value read - public decimal ReadDecimal() - { - this.ReadInternal(this.buffer, 16); - return this.BitConverter.ToDecimal(this.buffer, 0); - } - - /// - /// Reads a single character from the stream, using the character encoding for - /// this reader. If no characters have been fully read by the time the stream ends, - /// -1 is returned. - /// - /// The character read, or -1 for end of stream. - public int Read() - { - int charsRead = this.Read(this.charBuffer, 0, 1); - if (charsRead == 0) - { - return -1; - } - else - { - return this.charBuffer[0]; - } - } - - /// - /// Reads the specified number of characters into the given buffer, starting at - /// the given index. - /// - /// The buffer to copy data into - /// The first index to copy data into - /// The number of characters to read - /// The number of characters actually read. This will only be less than - /// the requested number of characters if the end of the stream is reached. - /// - public int Read(char[] data, int index, int count) - { - this.CheckDisposed(); - - // TODO: Use Guard - if (this.buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - if (index < 0) - { - throw new ArgumentOutOfRangeException("index"); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException("index"); - } - - if (count + index > data.Length) - { - throw new ArgumentException("Not enough space in buffer for specified number of characters starting at specified index"); - } - - int read = 0; - bool firstTime = true; - - // Use the normal buffer if we're only reading a small amount, otherwise - // use at most 4K at a time. - byte[] byteBuffer = this.buffer; - - if (byteBuffer.Length < count * this.minBytesPerChar) - { - byteBuffer = new byte[4096]; - } - - while (read < count) - { - int amountToRead; - - // First time through we know we haven't previously read any data - if (firstTime) - { - amountToRead = count * this.minBytesPerChar; - firstTime = false; - } - - // After that we can only assume we need to fully read 'chars left -1' characters - // and a single byte of the character we may be in the middle of - else - { - amountToRead = ((count - read - 1) * this.minBytesPerChar) + 1; - } - - if (amountToRead > byteBuffer.Length) - { - amountToRead = byteBuffer.Length; - } - - int bytesRead = this.TryReadInternal(byteBuffer, amountToRead); - if (bytesRead == 0) - { - return read; - } - - int decoded = this.decoder.GetChars(byteBuffer, 0, bytesRead, data, index); - read += decoded; - index += decoded; - } - - return read; - } - - /// - /// Reads the specified number of bytes into the given buffer, starting at - /// the given index. - /// - /// The buffer to copy data into - /// The first index to copy data into - /// The number of bytes to read - /// The number of bytes actually read. This will only be less than - /// the requested number of bytes if the end of the stream is reached. - /// - public int Read(byte[] buffer, int index, int count) - { - this.CheckDisposed(); - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - if (index < 0) - { - throw new ArgumentOutOfRangeException("index"); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException("index"); - } - - if (count + index > buffer.Length) - { - throw new ArgumentException("Not enough space in buffer for specified number of bytes starting at specified index"); - } - - int read = 0; - while (count > 0) - { - int block = this.BaseStream.Read(buffer, index, count); - if (block == 0) - { - return read; - } - - index += block; - read += block; - count -= block; - } - - return read; - } - - /// - /// Reads the specified number of bytes, returning them in a new byte array. - /// If not enough bytes are available before the end of the stream, this - /// method will return what is available. - /// - /// The number of bytes to read - /// The bytes read - public byte[] ReadBytes(int count) - { - this.CheckDisposed(); - if (count < 0) - { - throw new ArgumentOutOfRangeException("count"); - } - - byte[] ret = new byte[count]; - int index = 0; - while (index < count) - { - int read = this.BaseStream.Read(ret, index, count - index); - - // Stream has finished half way through. That's fine, return what we've got. - if (read == 0) - { - byte[] copy = new byte[index]; - Buffer.BlockCopy(ret, 0, copy, 0, index); - return copy; - } - - index += read; - } - - return ret; - } - - /// - /// Reads the specified number of bytes, returning them in a new byte array. - /// If not enough bytes are available before the end of the stream, this - /// method will throw an IOException. - /// - /// The number of bytes to read - /// The bytes read - public byte[] ReadBytesOrThrow(int count) - { - byte[] ret = new byte[count]; - this.ReadInternal(ret, count); - return ret; - } - - /// - /// Reads a 7-bit encoded integer from the stream. This is stored with the least significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. This method is not affected by the endianness - /// of the bit converter. - /// - /// The 7-bit encoded integer read from the stream. - public int Read7BitEncodedInt() - { - this.CheckDisposed(); - - int ret = 0; - for (int shift = 0; shift < 35; shift += 7) - { - int b = this.BaseStream.ReadByte(); - if (b == -1) - { - throw new EndOfStreamException(); - } - - ret = ret | ((b & 0x7f) << shift); - if ((b & 0x80) == 0) - { - return ret; - } - } - - // Still haven't seen a byte with the high bit unset? Dodgy data. - throw new IOException("Invalid 7-bit encoded integer in stream."); - } - - /// - /// Reads a 7-bit encoded integer from the stream. This is stored with the most significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. This method is not affected by the endianness - /// of the bit converter. - /// - /// The 7-bit encoded integer read from the stream. - public int ReadBigEndian7BitEncodedInt() - { - this.CheckDisposed(); - - int ret = 0; - for (int i = 0; i < 5; i++) - { - int b = this.BaseStream.ReadByte(); - if (b == -1) - { - throw new EndOfStreamException(); - } - - ret = (ret << 7) | (b & 0x7f); - if ((b & 0x80) == 0) - { - return ret; - } - } - - // Still haven't seen a byte with the high bit unset? Dodgy data. - throw new IOException("Invalid 7-bit encoded integer in stream."); - } - - /// - /// Reads a length-prefixed string from the stream, using the encoding for this reader. - /// A 7-bit encoded integer is first read, which specifies the number of bytes - /// to read from the stream. These bytes are then converted into a string with - /// the encoding for this reader. - /// - /// The string read from the stream. - public string ReadString() - { - int bytesToRead = this.Read7BitEncodedInt(); - - byte[] data = new byte[bytesToRead]; - this.ReadInternal(data, bytesToRead); - return this.Encoding.GetString(data, 0, data.Length); - } - - /// - /// Disposes of the underlying stream. - /// - public void Dispose() - { - if (!this.disposed) - { - this.disposed = true; - ((IDisposable)this.BaseStream).Dispose(); - } - } - - /// - /// Checks whether or not the reader has been disposed, throwing an exception if so. - /// - private void CheckDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException("EndianBinaryReader"); - } - } - - /// - /// Reads the given number of bytes from the stream, throwing an exception - /// if they can't all be read. - /// - /// Buffer to read into - /// Number of bytes to read - private void ReadInternal(byte[] data, int size) - { - this.CheckDisposed(); - int index = 0; - while (index < size) - { - int read = this.BaseStream.Read(data, index, size - index); - if (read == 0) - { - throw new EndOfStreamException( - string.Format( - "End of stream reached with {0} byte{1} left to read.", - size - index, - size - index == 1 ? "s" : string.Empty)); - } - - index += read; - } - } - - /// - /// Reads the given number of bytes from the stream if possible, returning - /// the number of bytes actually read, which may be less than requested if - /// (and only if) the end of the stream is reached. - /// - /// Buffer to read into - /// Number of bytes to read - /// Number of bytes actually read - private int TryReadInternal(byte[] data, int size) - { - this.CheckDisposed(); - int index = 0; - while (index < size) - { - int read = this.BaseStream.Read(data, index, size - index); - if (read == 0) - { - return index; - } - - index += read; - } - - return index; - } - } -} diff --git a/src/ImageSharp46/IO/EndianBinaryWriter.cs b/src/ImageSharp46/IO/EndianBinaryWriter.cs deleted file mode 100644 index b10ae79b4..000000000 --- a/src/ImageSharp46/IO/EndianBinaryWriter.cs +++ /dev/null @@ -1,385 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - using System; - using System.IO; - using System.Text; - - /// - /// Equivalent of , but with either endianness, depending on - /// the it is constructed with. - /// - internal class EndianBinaryWriter : IDisposable - { - /// - /// Buffer used for temporary storage during conversion from primitives - /// - private readonly byte[] buffer = new byte[16]; - - /// - /// Buffer used for Write(char) - /// - private readonly char[] charBuffer = new char[1]; - - /// - /// Whether or not this writer has been disposed yet. - /// - private bool disposed; - - /// - /// Initializes a new instance of the class - /// with the given bit converter, writing to the given stream, using UTF-8 encoding. - /// - /// Converter to use when writing data - /// Stream to write data to - public EndianBinaryWriter(EndianBitConverter bitConverter, Stream stream) - : this(bitConverter, stream, Encoding.UTF8) - { - } - - /// - /// Initializes a new instance of the class - /// with the given bit converter, writing to the given stream, using the given encoding. - /// - /// Converter to use when writing data - /// Stream to write data to - /// - /// Encoding to use when writing character data - /// - public EndianBinaryWriter(EndianBitConverter bitConverter, Stream stream, Encoding encoding) - { - // TODO: Use Guard - if (bitConverter == null) - { - throw new ArgumentNullException("bitConverter"); - } - - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - if (encoding == null) - { - throw new ArgumentNullException("encoding"); - } - - if (!stream.CanWrite) - { - throw new ArgumentException("Stream isn't writable", "stream"); - } - - this.BaseStream = stream; - this.BitConverter = bitConverter; - this.Encoding = encoding; - } - - /// - /// Gets the bit converter used to write values to the stream - /// - public EndianBitConverter BitConverter { get; } - - /// - /// Gets the encoding used to write strings - /// - public Encoding Encoding { get; } - - /// - /// Gets the underlying stream of the EndianBinaryWriter. - /// - public Stream BaseStream { get; } - - /// - /// Closes the writer, including the underlying stream. - /// - public void Close() - { - this.Dispose(); - } - - /// - /// Flushes the underlying stream. - /// - public void Flush() - { - this.CheckDisposed(); - this.BaseStream.Flush(); - } - - /// - /// Seeks within the stream. - /// - /// Offset to seek to. - /// Origin of seek operation. - public void Seek(int offset, SeekOrigin origin) - { - this.CheckDisposed(); - this.BaseStream.Seek(offset, origin); - } - - /// - /// Writes a boolean value to the stream. 1 byte is written. - /// - /// The value to write - public void Write(bool value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 1); - } - - /// - /// Writes a 16-bit signed integer to the stream, using the bit converter - /// for this writer. 2 bytes are written. - /// - /// The value to write - public void Write(short value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 2); - } - - /// - /// Writes a 32-bit signed integer to the stream, using the bit converter - /// for this writer. 4 bytes are written. - /// - /// The value to write - public void Write(int value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 4); - } - - /// - /// Writes a 64-bit signed integer to the stream, using the bit converter - /// for this writer. 8 bytes are written. - /// - /// The value to write - public void Write(long value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 8); - } - - /// - /// Writes a 16-bit unsigned integer to the stream, using the bit converter - /// for this writer. 2 bytes are written. - /// - /// The value to write - public void Write(ushort value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 2); - } - - /// - /// Writes a 32-bit unsigned integer to the stream, using the bit converter - /// for this writer. 4 bytes are written. - /// - /// The value to write - public void Write(uint value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 4); - } - - /// - /// Writes a 64-bit unsigned integer to the stream, using the bit converter - /// for this writer. 8 bytes are written. - /// - /// The value to write - public void Write(ulong value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 8); - } - - /// - /// Writes a single-precision floating-point value to the stream, using the bit converter - /// for this writer. 4 bytes are written. - /// - /// The value to write - public void Write(float value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 4); - } - - /// - /// Writes a double-precision floating-point value to the stream, using the bit converter - /// for this writer. 8 bytes are written. - /// - /// The value to write - public void Write(double value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 8); - } - - /// - /// Writes a decimal value to the stream, using the bit converter for this writer. - /// 16 bytes are written. - /// - /// The value to write - public void Write(decimal value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 16); - } - - /// - /// Writes a signed byte to the stream. - /// - /// The value to write - public void Write(byte value) - { - this.buffer[0] = value; - this.WriteInternal(this.buffer, 1); - } - - /// - /// Writes an unsigned byte to the stream. - /// - /// The value to write - public void Write(sbyte value) - { - this.buffer[0] = unchecked((byte)value); - this.WriteInternal(this.buffer, 1); - } - - /// - /// Writes an array of bytes to the stream. - /// - /// The values to write - public void Write(byte[] value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.WriteInternal(value, value.Length); - } - - /// - /// Writes a portion of an array of bytes to the stream. - /// - /// An array containing the bytes to write - /// The index of the first byte to write within the array - /// The number of bytes to write - public void Write(byte[] value, int offset, int count) - { - this.CheckDisposed(); - this.BaseStream.Write(value, offset, count); - } - - /// - /// Writes a single character to the stream, using the encoding for this writer. - /// - /// The value to write - public void Write(char value) - { - this.charBuffer[0] = value; - this.Write(this.charBuffer); - } - - /// - /// Writes an array of characters to the stream, using the encoding for this writer. - /// - /// An array containing the characters to write - public void Write(char[] value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.CheckDisposed(); - byte[] data = this.Encoding.GetBytes(value, 0, value.Length); - this.WriteInternal(data, data.Length); - } - - /// - /// Writes a string to the stream, using the encoding for this writer. - /// - /// The value to write. Must not be null. - /// value is null - public void Write(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.CheckDisposed(); - byte[] data = this.Encoding.GetBytes(value); - this.Write7BitEncodedInt(data.Length); - this.WriteInternal(data, data.Length); - } - - /// - /// Writes a 7-bit encoded integer from the stream. This is stored with the least significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. - /// - /// The 7-bit encoded integer to write to the stream - public void Write7BitEncodedInt(int value) - { - this.CheckDisposed(); - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Value must be greater than or equal to 0."); - } - - int index = 0; - while (value >= 128) - { - this.buffer[index++] = (byte)((value & 0x7f) | 0x80); - value = value >> 7; - index++; - } - - this.buffer[index++] = (byte)value; - this.BaseStream.Write(this.buffer, 0, index); - } - - /// - /// Checks whether or not the writer has been disposed, throwing an exception if so. - /// - private void CheckDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException("EndianBinaryWriter"); - } - } - - /// - /// Writes the specified number of bytes from the start of the given byte array, - /// after checking whether or not the writer has been disposed. - /// - /// The array of bytes to write from - /// The number of bytes to write - private void WriteInternal(byte[] bytes, int length) - { - this.CheckDisposed(); - this.BaseStream.Write(bytes, 0, length); - } - - /// - /// Disposes of the underlying stream. - /// - public void Dispose() - { - if (!this.disposed) - { - this.Flush(); - this.disposed = true; - ((IDisposable)this.BaseStream).Dispose(); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/IO/EndianBitConverter.cs b/src/ImageSharp46/IO/EndianBitConverter.cs deleted file mode 100644 index d7a8d91fa..000000000 --- a/src/ImageSharp46/IO/EndianBitConverter.cs +++ /dev/null @@ -1,724 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - using System; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.InteropServices; - - /// - /// Equivalent of , but with either endianness. - /// - /// Adapted from Miscellaneous Utility Library - /// This product includes software developed by Jon Skeet and Marc Gravell. Contact , or see - /// . - /// - /// - [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "Reviewed. Suppression is OK here. Better readability.")] - [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed. Suppression is OK here. Better readability.")] - [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:StaticElementsMustAppearBeforeInstanceElements", Justification = "Reviewed. Suppression is OK here. Better readability.")] - internal abstract class EndianBitConverter - { - #region Endianness of this converter - /// - /// Indicates the byte order ("endianness") in which data is converted using this class. - /// - /// - /// Different computer architectures store data using different byte orders. "Big-endian" - /// means the most significant byte is on the left end of a word. "Little-endian" means the - /// most significant byte is on the right end of a word. - /// - /// true if this converter is little-endian, false otherwise. - public abstract bool IsLittleEndian(); - - /// - /// Gets the byte order ("endianness") in which data is converted using this class. - /// - public abstract Endianness Endianness { get; } - #endregion - - #region Factory properties - /// - /// The little-endian bit converter. - /// - private static readonly LittleEndianBitConverter LittleConverter = new LittleEndianBitConverter(); - - /// - /// Gets a little-endian bit converter instance. The same instance is - /// always returned. - /// - public static LittleEndianBitConverter Little => LittleConverter; - - /// - /// The big-endian bit converter. - /// - private static readonly BigEndianBitConverter BigConverter = new BigEndianBitConverter(); - - /// - /// Gets a big-endian bit converter instance. The same instance is - /// always returned. - /// - public static BigEndianBitConverter Big => BigConverter; - #endregion - - #region Double/primitive conversions - /// - /// Converts the specified double-precision floating point number to a - /// 64-bit signed integer. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A 64-bit signed integer whose value is equivalent to value. - public long DoubleToInt64Bits(double value) - { - return BitConverter.DoubleToInt64Bits(value); - } - - /// - /// Converts the specified 64-bit signed integer to a double-precision - /// floating point number. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A double-precision floating point number whose value is equivalent to value. - public double Int64BitsToDouble(long value) - { - return BitConverter.Int64BitsToDouble(value); - } - - /// - /// Converts the specified single-precision floating point number to a - /// 32-bit signed integer. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A 32-bit signed integer whose value is equivalent to value. - public int SingleToInt32Bits(float value) - { - return new Int32SingleUnion(value).AsInt32; - } - - /// - /// Converts the specified 32-bit signed integer to a single-precision floating point - /// number. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A single-precision floating point number whose value is equivalent to value. - public float Int32BitsToSingle(int value) - { - return new Int32SingleUnion(value).AsSingle; - } - #endregion - - #region To(PrimitiveType) conversions - /// - /// Returns a Boolean value converted from one byte at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// true if the byte at startIndex in value is nonzero; otherwise, false. - public bool ToBoolean(byte[] value, int startIndex) - { - CheckByteArgument(value, startIndex, 1); - return BitConverter.ToBoolean(value, startIndex); - } - - /// - /// Returns a Unicode character converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A character formed by two bytes beginning at startIndex. - public char ToChar(byte[] value, int startIndex) - { - return unchecked((char)this.CheckedFromBytes(value, startIndex, 2)); - } - - /// - /// Returns a double-precision floating point number converted from eight bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A double precision floating point number formed by eight bytes beginning at startIndex. - public double ToDouble(byte[] value, int startIndex) - { - return this.Int64BitsToDouble(this.ToInt64(value, startIndex)); - } - - /// - /// Returns a single-precision floating point number converted from four bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A single precision floating point number formed by four bytes beginning at startIndex. - public float ToSingle(byte[] value, int startIndex) - { - return this.Int32BitsToSingle(this.ToInt32(value, startIndex)); - } - - /// - /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 16-bit signed integer formed by two bytes beginning at startIndex. - public short ToInt16(byte[] value, int startIndex) - { - return unchecked((short)this.CheckedFromBytes(value, startIndex, 2)); - } - - /// - /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 32-bit signed integer formed by four bytes beginning at startIndex. - public int ToInt32(byte[] value, int startIndex) - { - return unchecked((int)this.CheckedFromBytes(value, startIndex, 4)); - } - - /// - /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 64-bit signed integer formed by eight bytes beginning at startIndex. - public long ToInt64(byte[] value, int startIndex) - { - return this.CheckedFromBytes(value, startIndex, 8); - } - - /// - /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 16-bit unsigned integer formed by two bytes beginning at startIndex. - public ushort ToUInt16(byte[] value, int startIndex) - { - return unchecked((ushort)this.CheckedFromBytes(value, startIndex, 2)); - } - - /// - /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 32-bit unsigned integer formed by four bytes beginning at startIndex. - public uint ToUInt32(byte[] value, int startIndex) - { - return unchecked((uint)this.CheckedFromBytes(value, startIndex, 4)); - } - - /// - /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 64-bit unsigned integer formed by eight bytes beginning at startIndex. - public ulong ToUInt64(byte[] value, int startIndex) - { - return unchecked((ulong)this.CheckedFromBytes(value, startIndex, 8)); - } - - /// - /// Convert the given number of bytes from the given array, from the given start - /// position, into a long, using the bytes as the least significant part of the long. - /// By the time this is called, the arguments have been checked for validity. - /// - /// The bytes to convert - /// The index of the first byte to convert - /// The number of bytes to use in the conversion - /// The converted number - protected internal abstract long FromBytes(byte[] value, int startIndex, int bytesToConvert); - - /// - /// Checks the given argument for validity. - /// - /// The byte array passed in - /// The start index passed in - /// The number of bytes required - /// value is a null reference - /// - /// startIndex is less than zero or greater than the length of value minus bytesRequired. - /// - [SuppressMessage("ReSharper", "UnusedParameter.Local", Justification = "Keeps code DRY")] - private static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (startIndex < 0 || startIndex > value.Length - bytesRequired) - { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - } - - /// - /// Checks the arguments for validity before calling FromBytes - /// (which can therefore assume the arguments are valid). - /// - /// The bytes to convert after checking - /// The index of the first byte to convert - /// The number of bytes to convert - /// The - private long CheckedFromBytes(byte[] value, int startIndex, int bytesToConvert) - { - CheckByteArgument(value, startIndex, bytesToConvert); - return this.FromBytes(value, startIndex, bytesToConvert); - } - #endregion - - #region ToString conversions - /// - /// Returns a String converted from the elements of a byte array. - /// - /// An array of bytes. - /// All the elements of value are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value) - { - return BitConverter.ToString(value); - } - - /// - /// Returns a String converted from the elements of a byte array starting at a specified array position. - /// - /// An array of bytes. - /// The starting position within value. - /// The elements from array position startIndex to the end of the array are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value, int startIndex) - { - return BitConverter.ToString(value, startIndex); - } - - /// - /// Returns a String converted from a specified number of bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// The number of bytes to convert. - /// The length elements from array position startIndex are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value, int startIndex, int length) - { - return BitConverter.ToString(value, startIndex, length); - } - #endregion - - #region Decimal conversions - /// - /// Returns a decimal value converted from sixteen bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A decimal formed by sixteen bytes beginning at startIndex. - public decimal ToDecimal(byte[] value, int startIndex) - { - // HACK: This always assumes four parts, each in their own endianness, - // starting with the first part at the start of the byte array. - // On the other hand, there's no real format specified... - int[] parts = new int[4]; - for (int i = 0; i < 4; i++) - { - parts[i] = this.ToInt32(value, startIndex + (i * 4)); - } - - return new decimal(parts); - } - - /// - /// Returns the specified decimal value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 16. - public byte[] GetBytes(decimal value) - { - byte[] bytes = new byte[16]; - int[] parts = decimal.GetBits(value); - for (int i = 0; i < 4; i++) - { - this.CopyBytesImpl(parts[i], 4, bytes, i * 4); - } - - return bytes; - } - - /// - /// Copies the specified decimal value into the specified byte array, - /// beginning at the specified index. - /// - /// A character to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(decimal value, byte[] buffer, int index) - { - int[] parts = decimal.GetBits(value); - for (int i = 0; i < 4; i++) - { - this.CopyBytesImpl(parts[i], 4, buffer, (i * 4) + index); - } - } - #endregion - - #region GetBytes conversions - /// - /// Returns an array with the given number of bytes formed - /// from the least significant bytes of the specified value. - /// This is used to implement the other GetBytes methods. - /// - /// The value to get bytes for - /// The number of significant bytes to return - /// - /// The . - /// - private byte[] GetBytes(long value, int bytes) - { - byte[] buffer = new byte[bytes]; - this.CopyBytes(value, bytes, buffer, 0); - return buffer; - } - - /// - /// Returns the specified Boolean value as an array of bytes. - /// - /// A Boolean value. - /// An array of bytes with length 1. - /// - /// The . - /// - public byte[] GetBytes(bool value) - { - return BitConverter.GetBytes(value); - } - - /// - /// Returns the specified Unicode character value as an array of bytes. - /// - /// A character to convert. - /// An array of bytes with length 2. - /// - /// The . - /// - public byte[] GetBytes(char value) - { - return this.GetBytes(value, 2); - } - - /// - /// Returns the specified double-precision floating point value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public byte[] GetBytes(double value) - { - return this.GetBytes(this.DoubleToInt64Bits(value), 8); - } - - /// - /// Returns the specified 16-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 2. - public byte[] GetBytes(short value) - { - return this.GetBytes(value, 2); - } - - /// - /// Returns the specified 32-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public byte[] GetBytes(int value) - { - return this.GetBytes(value, 4); - } - - /// - /// Returns the specified 64-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public byte[] GetBytes(long value) - { - return this.GetBytes(value, 8); - } - - /// - /// Returns the specified single-precision floating point value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public byte[] GetBytes(float value) - { - return this.GetBytes(this.SingleToInt32Bits(value), 4); - } - - /// - /// Returns the specified 16-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 2. - public byte[] GetBytes(ushort value) - { - return this.GetBytes(value, 2); - } - - /// - /// Returns the specified 32-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public byte[] GetBytes(uint value) - { - return this.GetBytes(value, 4); - } - - /// - /// Returns the specified 64-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public byte[] GetBytes(ulong value) - { - return this.GetBytes(unchecked((long)value), 8); - } - - #endregion - - #region CopyBytes conversions - /// - /// Copies the given number of bytes from the least-specific - /// end of the specified value into the specified byte array, beginning - /// at the specified index. - /// This is used to implement the other CopyBytes methods. - /// - /// The value to copy bytes for - /// The number of significant bytes to copy - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - private void CopyBytes(long value, int bytes, byte[] buffer, int index) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer), "Byte array must not be null"); - } - - if (buffer.Length < index + bytes) - { - throw new ArgumentOutOfRangeException(nameof(buffer), "Buffer not big enough for value"); - } - - this.CopyBytesImpl(value, bytes, buffer, index); - } - - /// - /// Copies the given number of bytes from the least-specific - /// end of the specified value into the specified byte array, beginning - /// at the specified index. - /// This must be implemented in concrete derived classes, but the implementation - /// may assume that the value will fit into the buffer. - /// - /// The value to copy bytes for - /// The number of significant bytes to copy - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - protected internal abstract void CopyBytesImpl(long value, int bytes, byte[] buffer, int index); - - /// - /// Copies the specified Boolean value into the specified byte array, - /// beginning at the specified index. - /// - /// A Boolean value. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(bool value, byte[] buffer, int index) - { - this.CopyBytes(value ? 1 : 0, 1, buffer, index); - } - - /// - /// Copies the specified Unicode character value into the specified byte array, - /// beginning at the specified index. - /// - /// A character to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(char value, byte[] buffer, int index) - { - this.CopyBytes(value, 2, buffer, index); - } - - /// - /// Copies the specified double-precision floating point value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(double value, byte[] buffer, int index) - { - this.CopyBytes(this.DoubleToInt64Bits(value), 8, buffer, index); - } - - /// - /// Copies the specified 16-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(short value, byte[] buffer, int index) - { - this.CopyBytes(value, 2, buffer, index); - } - - /// - /// Copies the specified 32-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(int value, byte[] buffer, int index) - { - this.CopyBytes(value, 4, buffer, index); - } - - /// - /// Copies the specified 64-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(long value, byte[] buffer, int index) - { - this.CopyBytes(value, 8, buffer, index); - } - - /// - /// Copies the specified single-precision floating point value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(float value, byte[] buffer, int index) - { - this.CopyBytes(this.SingleToInt32Bits(value), 4, buffer, index); - } - - /// - /// Copies the specified 16-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(ushort value, byte[] buffer, int index) - { - this.CopyBytes(value, 2, buffer, index); - } - - /// - /// Copies the specified 32-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(uint value, byte[] buffer, int index) - { - this.CopyBytes(value, 4, buffer, index); - } - - /// - /// Copies the specified 64-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(ulong value, byte[] buffer, int index) - { - this.CopyBytes(unchecked((long)value), 8, buffer, index); - } - - #endregion - - #region Private struct used for Single/Int32 conversions - /// - /// Union used solely for the equivalent of DoubleToInt64Bits and vice versa. - /// - [StructLayout(LayoutKind.Explicit)] - private struct Int32SingleUnion - { - /// - /// Int32 version of the value. - /// - [FieldOffset(0)] - private readonly int i; - - /// - /// Single version of the value. - /// - [FieldOffset(0)] - private readonly float f; - - /// - /// Initializes a new instance of the struct. - /// - /// The integer value of the new instance. - internal Int32SingleUnion(int i) - { - this.f = 0; // Just to keep the compiler happy - this.i = i; - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The floating point value of the new instance. - /// - internal Int32SingleUnion(float f) - { - this.i = 0; // Just to keep the compiler happy - this.f = f; - } - - /// - /// Gets the value of the instance as an integer. - /// - internal int AsInt32 => this.i; - - /// - /// Gets the value of the instance as a floating point number. - /// - internal float AsSingle => this.f; - } - #endregion - } -} \ No newline at end of file diff --git a/src/ImageSharp46/IO/Endianness.cs b/src/ImageSharp46/IO/Endianness.cs deleted file mode 100644 index aefda6dc4..000000000 --- a/src/ImageSharp46/IO/Endianness.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - /// - /// Endianness of a converter - /// - internal enum Endianness - { - /// - /// Little endian - least significant byte first - /// - LittleEndian, - - /// - /// Big endian - most significant byte first - /// - BigEndian - } -} diff --git a/src/ImageSharp46/IO/LittleEndianBitConverter.cs b/src/ImageSharp46/IO/LittleEndianBitConverter.cs deleted file mode 100644 index 63ebe18a3..000000000 --- a/src/ImageSharp46/IO/LittleEndianBitConverter.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.IO -{ - /// - /// Implementation of EndianBitConverter which converts to/from little-endian - /// byte arrays. - /// - /// Adapted from Miscellaneous Utility Library - /// This product includes software developed by Jon Skeet and Marc Gravell. Contact , or see - /// . - /// - /// - internal sealed class LittleEndianBitConverter : EndianBitConverter - { - /// - public override Endianness Endianness => Endianness.LittleEndian; - - /// - public override bool IsLittleEndian() => true; - - /// - protected internal override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index) - { - for (int i = 0; i < bytes; i++) - { - buffer[i + index] = unchecked((byte)(value & 0xff)); - value = value >> 8; - } - } - - /// - protected internal override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert) - { - long ret = 0; - for (int i = 0; i < bytesToConvert; i++) - { - ret = unchecked((ret << 8) | buffer[startIndex + bytesToConvert - 1 - i]); - } - - return ret; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Image.cs b/src/ImageSharp46/Image.cs deleted file mode 100644 index 83a4b9dff..000000000 --- a/src/ImageSharp46/Image.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Diagnostics; - using System.IO; - - /// - /// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha - /// packed into a single unsigned integer value. - /// - [DebuggerDisplay("Image: {Width}x{Height}")] - public class Image : Image - { - /// - /// Initializes a new instance of the class - /// with the height and the width of the image. - /// - public Image() - { - } - - /// - /// Initializes a new instance of the class - /// with the height and the width of the image. - /// - /// The width of the image in pixels. - /// The height of the image in pixels. - public Image(int width, int height) - : base(width, height) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The stream containing image information. - /// - /// Thrown if the is null. - public Image(Stream stream) - : base(stream) - { - } - - /// - /// Initializes a new instance of the class - /// by making a copy from another image. - /// - /// The other image, where the clone should be made from. - /// is null. - public Image(Image other) - : base(other) - { - } - - /// - public override PixelAccessor Lock() - { - return new PixelAccessor(this); - } - } -} diff --git a/src/ImageSharp46/Image/IImageBase.cs b/src/ImageSharp46/Image/IImageBase.cs deleted file mode 100644 index 3168b4bb5..000000000 --- a/src/ImageSharp46/Image/IImageBase.cs +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Encapsulates the basic properties and methods required to manipulate images in varying formats. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IImageBase : IImageBase - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Gets the pixels as an array of the given packed pixel format. - /// - TColor[] Pixels { get; } - - /// - /// Sets the size of the pixel array of the image to the given width and height. - /// - /// The new width of the image. Must be greater than zero. - /// The new height of the image. Must be greater than zero. - /// - /// Thrown if either or are less than or equal to 0. - /// - void InitPixels(int width, int height); - - /// - /// Sets the pixel array of the image to the given value. - /// - /// The new width of the image. Must be greater than zero. - /// The new height of the image. Must be greater than zero. - /// The array with pixels. Must be a multiple of the width and height. - /// - /// Thrown if either or are less than or equal to 0. - /// - /// - /// Thrown if the length is not equal to Width * Height. - /// - void SetPixels(int width, int height, TColor[] pixels); - - /// - /// Sets the pixel array of the image to the given value, creating a copy of - /// the original pixels. - /// - /// The new width of the image. Must be greater than zero. - /// The new height of the image. Must be greater than zero. - /// The array with pixels. Must be a multiple of four times the width and height. - /// - /// Thrown if either or are less than or equal to 0. - /// - /// - /// Thrown if the length is not equal to Width * Height. - /// - void ClonePixels(int width, int height, TColor[] pixels); - - /// - /// Locks the image providing access to the pixels. - /// - /// It is imperative that the accessor is correctly disposed off after use. - /// - /// - /// The - PixelAccessor Lock(); - } - - /// - /// Encapsulates the basic properties and methods required to manipulate images. - /// - public interface IImageBase - { - /// - /// Gets the representing the bounds of the image. - /// - Rectangle Bounds { get; } - - /// - /// Gets or sets the quality of the image. This affects the output quality of lossy image formats. - /// - int Quality { get; set; } - - /// - /// Gets or sets the frame delay for animated images. - /// If not 0, this field specifies the number of hundredths (1/100) of a second to - /// wait before continuing with the processing of the Data Stream. - /// The clock starts ticking immediately after the graphic is rendered. - /// - int FrameDelay { get; set; } - - /// - /// Gets or sets the maximum allowable width in pixels. - /// - int MaxWidth { get; set; } - - /// - /// Gets or sets the maximum allowable height in pixels. - /// - int MaxHeight { get; set; } - - /// - /// Gets the width in pixels. - /// - int Width { get; } - - /// - /// Gets the height in pixels. - /// - int Height { get; } - - /// - /// Gets the pixel ratio made up of the width and height. - /// - double PixelRatio { get; } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Image/IImageFrame.cs b/src/ImageSharp46/Image/IImageFrame.cs deleted file mode 100644 index f6f856b22..000000000 --- a/src/ImageSharp46/Image/IImageFrame.cs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Represents a single frame in a animation. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IImageFrame : IImageBase - where TColor : struct, IPackedPixel - where TPacked : struct - { - } -} diff --git a/src/ImageSharp46/Image/IImageProcessor.cs b/src/ImageSharp46/Image/IImageProcessor.cs deleted file mode 100644 index 145e83136..000000000 --- a/src/ImageSharp46/Image/IImageProcessor.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Threading.Tasks; - - /// - /// Encapsulates methods to alter the pixels of an image. - /// - public interface IImageProcessor - { - /// - /// Gets or sets the parallel options for processing tasks in parallel. - /// - ParallelOptions ParallelOptions { get; set; } - - /// - /// Gets or sets a value indicating whether to compress - /// or expand individual pixel colors the value on processing. - /// - bool Compand { get; set; } - } -} diff --git a/src/ImageSharp46/Image/Image.cs b/src/ImageSharp46/Image/Image.cs deleted file mode 100644 index 337f38fcf..000000000 --- a/src/ImageSharp46/Image/Image.cs +++ /dev/null @@ -1,361 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Text; - - using Formats; - - /// - /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. - /// - /// The pixel format. - /// The packed format. uint, long, float. - [DebuggerDisplay("Image: {Width}x{Height}")] - public class Image : ImageBase - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The default horizontal resolution value (dots per inch) in x direction. - /// The default value is 96 dots per inch. - /// - public const double DefaultHorizontalResolution = 96; - - /// - /// The default vertical resolution value (dots per inch) in y direction. - /// The default value is 96 dots per inch. - /// - public const double DefaultVerticalResolution = 96; - - /// - /// Initializes a new instance of the class. - /// - public Image() - { - this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); - } - - /// - /// Initializes a new instance of the class - /// with the height and the width of the image. - /// - /// The width of the image in pixels. - /// The height of the image in pixels. - public Image(int width, int height) - : base(width, height) - { - this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The stream containing image information. - /// - /// Thrown if the is null. - public Image(Stream stream) - { - Guard.NotNull(stream, nameof(stream)); - this.Load(stream); - } - - /// - /// Initializes a new instance of the class - /// by making a copy from another image. - /// - /// The other image, where the clone should be made from. - /// is null. - public Image(Image other) - : base(other) - { - foreach (ImageFrame frame in other.Frames) - { - if (frame != null) - { - this.Frames.Add(new ImageFrame(frame)); - } - } - - this.CopyProperties(other); - } - - /// - /// Gets a list of supported image formats. - /// - public IReadOnlyCollection Formats { get; } = Bootstrapper.Instance.ImageFormats; - - /// - /// Gets or sets the resolution of the image in x- direction. It is defined as - /// number of dots per inch and should be an positive value. - /// - /// The density of the image in x- direction. - public double HorizontalResolution { get; set; } = DefaultHorizontalResolution; - - /// - /// Gets or sets the resolution of the image in y- direction. It is defined as - /// number of dots per inch and should be an positive value. - /// - /// The density of the image in y- direction. - public double VerticalResolution { get; set; } = DefaultVerticalResolution; - - /// - /// Gets the width of the image in inches. It is calculated as the width of the image - /// in pixels multiplied with the density. When the density is equals or less than zero - /// the default value is used. - /// - /// The width of the image in inches. - public double InchWidth - { - get - { - double resolution = this.HorizontalResolution; - - if (resolution <= 0) - { - resolution = DefaultHorizontalResolution; - } - - return this.Width / resolution; - } - } - - /// - /// Gets the height of the image in inches. It is calculated as the height of the image - /// in pixels multiplied with the density. When the density is equals or less than zero - /// the default value is used. - /// - /// The height of the image in inches. - public double InchHeight - { - get - { - double resolution = this.VerticalResolution; - - if (resolution <= 0) - { - resolution = DefaultVerticalResolution; - } - - return this.Height / resolution; - } - } - - /// - /// Gets a value indicating whether this image is animated. - /// - /// - /// True if this image is animated; otherwise, false. - /// - public bool IsAnimated => this.Frames.Count > 0; - - /// - /// Gets or sets the number of times any animation is repeated. - /// 0 means to repeat indefinitely. - /// - public ushort RepeatCount { get; set; } - - /// - /// Gets the other frames for the animation. - /// - /// The list of frame images. - public IList> Frames { get; } = new List>(); - - /// - /// Gets the list of properties for storing meta information about this image. - /// - /// A list of image properties. - public IList Properties { get; } = new List(); - - /// - /// Gets the currently loaded image format. - /// - public IImageFormat CurrentImageFormat { get; internal set; } - - /// - /// Gets or sets the Exif profile. - /// - public ExifProfile ExifProfile { get; set; } - - /// - /// Saves the image to the given stream using the currently loaded image format. - /// - /// The stream to save the image to. - /// Thrown if the stream is null. - public Image Save(Stream stream) - { - Guard.NotNull(stream, nameof(stream)); - this.CurrentImageFormat.Encoder.Encode(this, stream); - return this; - } - - /// - /// Saves the image to the given stream using the given image format. - /// - /// The stream to save the image to. - /// The format to save the image as. - /// Thrown if the stream is null. - public Image Save(Stream stream, IImageFormat format) - { - Guard.NotNull(stream, nameof(stream)); - format.Encoder.Encode(this, stream); - return this; - } - - /// - /// Saves the image to the given stream using the given image encoder. - /// - /// The stream to save the image to. - /// The encoder to save the image with. - /// Thrown if the stream is null. - /// - /// The . - /// - public Image Save(Stream stream, IImageEncoder encoder) - { - Guard.NotNull(stream, nameof(stream)); - encoder.Encode(this, stream); - - // Reset to the start of the stream. - if (stream.CanSeek) - { - stream.Position = 0; - } - - return this; - } - - /// - public override string ToString() - { - return $"Image: {this.Width}x{this.Height}"; - } - - /// - /// Returns a Base64 encoded string from the given image. - /// - /// data:image/gif;base64,R0lGODlhAQABAIABAEdJRgAAACwAAAAAAQABAAACAkQBAA== - /// The - public string ToBase64String() - { - using (MemoryStream stream = new MemoryStream()) - { - this.Save(stream); - stream.Flush(); - return $"data:{this.CurrentImageFormat.Encoder.MimeType};base64,{Convert.ToBase64String(stream.ToArray())}"; - } - } - - /// - /// Copies the properties from the other . - /// - /// - /// The other to copy the properties from. - /// - internal void CopyProperties(Image other) - { - base.CopyProperties(other); - - this.HorizontalResolution = other.HorizontalResolution; - this.VerticalResolution = other.VerticalResolution; - this.CurrentImageFormat = other.CurrentImageFormat; - this.RepeatCount = other.RepeatCount; - - if (other.ExifProfile != null) - { - this.ExifProfile = new ExifProfile(other.ExifProfile); - } - } - - /// - /// Loads the image from the given stream. - /// - /// The stream containing image information. - /// - /// Thrown if the stream is not readable nor seekable. - /// - private void Load(Stream stream) - { - if (!this.Formats.Any()) - { - return; - } - - if (!stream.CanRead) - { - throw new NotSupportedException("Cannot read from the stream."); - } - - if (stream.CanSeek) - { - if (this.Decode(stream)) - { - return; - } - } - else - { - // We want to be able to load images from things like HttpContext.Request.Body - using (MemoryStream ms = new MemoryStream()) - { - stream.CopyTo(ms); - ms.Position = 0; - - if (this.Decode(ms)) - { - return; - } - } - } - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine("Image cannot be loaded. Available formats:"); - - foreach (IImageFormat format in this.Formats) - { - stringBuilder.AppendLine("-" + format); - } - - throw new NotSupportedException(stringBuilder.ToString()); - } - - /// - /// Decodes the image stream to the current image. - /// - /// The stream. - /// - /// The . - /// - private bool Decode(Stream stream) - { - int maxHeaderSize = this.Formats.Max(x => x.Decoder.HeaderSize); - if (maxHeaderSize > 0) - { - byte[] header = new byte[maxHeaderSize]; - - stream.Position = 0; - stream.Read(header, 0, maxHeaderSize); - stream.Position = 0; - - IImageFormat format = this.Formats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header)); - if (format != null) - { - format.Decoder.Decode(this, stream); - this.CurrentImageFormat = format; - return true; - } - } - - return false; - } - } -} diff --git a/src/ImageSharp46/Image/ImageBase.cs b/src/ImageSharp46/Image/ImageBase.cs deleted file mode 100644 index 7e9ca2701..000000000 --- a/src/ImageSharp46/Image/ImageBase.cs +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Diagnostics; - - /// - /// The base class of all images. Encapsulates the basic properties and methods required to manipulate - /// images in different pixel formats. - /// - /// The pixel format. - /// The packed format. uint, long, float. - [DebuggerDisplay("Image: {Width}x{Height}")] - public abstract class ImageBase : IImageBase - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The image pixels - /// - private TColor[] pixelBuffer; - - /// - /// Initializes a new instance of the class. - /// - protected ImageBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The width of the image in pixels. - /// The height of the image in pixels. - /// - /// Thrown if either or are less than or equal to 0. - /// - protected ImageBase(int width, int height) - { - this.InitPixels(width, height); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The other to create this instance from. - /// - /// - /// Thrown if the given is null. - /// - protected ImageBase(ImageBase other) - { - Guard.NotNull(other, nameof(other), "Other image cannot be null."); - - this.Width = other.Width; - this.Height = other.Height; - this.CopyProperties(other); - - // Copy the pixels. Unsafe.CopyBlock gives us a nice speed boost here. - this.pixelBuffer = new TColor[this.Width * this.Height]; - using (PixelAccessor sourcePixels = other.Lock()) - using (PixelAccessor target = this.Lock()) - { - sourcePixels.CopyImage(target); - } - } - - /// - public int MaxWidth { get; set; } = int.MaxValue; - - /// - public int MaxHeight { get; set; } = int.MaxValue; - - /// - public TColor[] Pixels => this.pixelBuffer; - - /// - public int Width { get; private set; } - - /// - public int Height { get; private set; } - - /// - public double PixelRatio => (double)this.Width / this.Height; - - /// - public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height); - - /// - public int Quality { get; set; } - - /// - public int FrameDelay { get; set; } - - /// - public void InitPixels(int width, int height) - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - - this.Width = width; - this.Height = height; - this.pixelBuffer = new TColor[width * height]; - } - - /// - public void SetPixels(int width, int height, TColor[] pixels) - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(pixels, nameof(pixels)); - - if (pixels.Length != width * height) - { - throw new ArgumentException("Pixel array must have the length of Width * Height."); - } - - this.Width = width; - this.Height = height; - this.pixelBuffer = pixels; - } - - /// - public void ClonePixels(int width, int height, TColor[] pixels) - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(pixels, nameof(pixels)); - - if (pixels.Length != width * height) - { - throw new ArgumentException("Pixel array must have the length of Width * Height."); - } - - this.Width = width; - this.Height = height; - - // Copy the pixels. TODO: use Unsafe.Copy. - this.pixelBuffer = new TColor[pixels.Length]; - Array.Copy(pixels, this.pixelBuffer, pixels.Length); - } - - /// - public virtual PixelAccessor Lock() - { - return new PixelAccessor(this); - } - - /// - /// Copies the properties from the other . - /// - /// - /// The other to copy the properties from. - /// - protected void CopyProperties(ImageBase other) - { - this.Quality = other.Quality; - this.FrameDelay = other.FrameDelay; - } - } -} diff --git a/src/ImageSharp46/Image/ImageFrame.cs b/src/ImageSharp46/Image/ImageFrame.cs deleted file mode 100644 index fa576c4eb..000000000 --- a/src/ImageSharp46/Image/ImageFrame.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Represents a single frame in a animation. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class ImageFrame : ImageBase - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - public ImageFrame() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The frame to create the frame from. - /// - public ImageFrame(ImageFrame frame) - : base(frame) - { - } - - /// - public override string ToString() - { - return $"ImageFrame: {this.Width}x{this.Height}"; - } - } -} diff --git a/src/ImageSharp46/Image/ImageIOExtensions.cs b/src/ImageSharp46/Image/ImageIOExtensions.cs deleted file mode 100644 index bb0369d8a..000000000 --- a/src/ImageSharp46/Image/ImageIOExtensions.cs +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.IO; - - using Formats; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Saves the image to the given stream with the bmp format. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The stream to save the image to. - /// Thrown if the stream is null. - /// - /// The . - /// - public static Image SaveAsBmp(this Image source, Stream stream) - where TColor : struct, IPackedPixel - where TPacked : struct - => source.Save(stream, new BmpEncoder()); - - /// - /// Saves the image to the given stream with the png format. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The stream to save the image to. - /// The quality to save the image to representing the number of colors. - /// Anything equal to 256 and below will cause the encoder to save the image in an indexed format. - /// - /// Thrown if the stream is null. - /// - /// The . - /// - public static Image SaveAsPng(this Image source, Stream stream, int quality = int.MaxValue) - where TColor : struct, IPackedPixel - where TPacked : struct - => source.Save(stream, new PngEncoder { Quality = quality }); - - /// - /// Saves the image to the given stream with the jpeg format. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The stream to save the image to. - /// The quality to save the image to. Between 1 and 100. - /// Thrown if the stream is null. - /// - /// The . - /// - public static Image SaveAsJpeg(this Image source, Stream stream, int quality = 75) - where TColor : struct, IPackedPixel - where TPacked : struct - => source.Save(stream, new JpegEncoder { Quality = quality }); - - /// - /// Saves the image to the given stream with the gif format. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The stream to save the image to. - /// The quality to save the image to representing the number of colors. Between 1 and 256. - /// Thrown if the stream is null. - /// - /// The . - /// - public static Image SaveAsGif(this Image source, Stream stream, int quality = 256) - where TColor : struct, IPackedPixel - where TPacked : struct - => source.Save(stream, new GifEncoder { Quality = quality }); - } -} diff --git a/src/ImageSharp46/Image/ImageProcessingExtensions.cs b/src/ImageSharp46/Image/ImageProcessingExtensions.cs deleted file mode 100644 index e4b9ff3fd..000000000 --- a/src/ImageSharp46/Image/ImageProcessingExtensions.cs +++ /dev/null @@ -1,203 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies the processor to the image. - /// This method does not resize the target image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The processor to apply to the image. - /// The . - internal static Image Process(this Image source, IImageFilter processor) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Process(source, source.Bounds, processor); - } - - /// - /// Applies the processor to the image. - /// This method does not resize the target image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The processors to apply to the image. - /// The . - internal static Image Process(this Image source, Rectangle sourceRectangle, IImageFilter processor) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return PerformAction(source, (sourceImage) => processor.Apply(sourceImage, sourceRectangle)); - } - - /// - /// Applies the processor to the image. - /// This method does not resize the target image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The processor to apply to the image. - /// The . - internal static Image Process(this Image source, IImageSampler processor) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Process(source, source.Bounds, processor); - } - - /// - /// Applies the processor to the image. - /// This method does not resize the target image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The processors to apply to the image. - /// The . - internal static Image Process(this Image source, Rectangle sourceRectangle, IImageSampler processor) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle)); - } - - /// - /// Applies the processor to the image. - /// - /// This method resizes the image. - /// - /// - /// The pixel format. - /// The packed format. long, float. - /// The source image. Cannot be null. - /// The target image width. - /// The target image height. - /// The processor to apply to the image. - /// The . - internal static Image Process(this Image source, int width, int height, IImageSampler sampler) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Process(source, width, height, source.Bounds, default(Rectangle), sampler); - } - - /// - /// Applies the processor to the image. - /// - /// This method does will resize the target image if the source and target rectangles are different. - /// - /// - /// The pixel format. - /// The packed format. long, float. - /// The source image. Cannot be null. - /// The target image width. - /// The target image height. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// The structure that specifies the location and size of the drawn image. - /// The image is scaled to fit the rectangle. - /// - /// The processor to apply to the image. - /// The . - internal static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); - } - - /// - /// Performs the given action on the source image. - /// - /// The pixel format. - /// The packed format. long, float. - /// The image to perform the action against. - /// The to perform against the image. - /// The . - private static Image PerformAction(Image source, Action> action) - where TColor : struct, IPackedPixel - where TPacked : struct - { - action(source); - - foreach (ImageFrame sourceFrame in source.Frames) - { - action(sourceFrame); - } - - return source; - } - - /// - /// Performs the given action on the source image. - /// - /// The pixel format. - /// The packed format. long, float. - /// The image to perform the action against. - /// Whether to clone the image. - /// The to perform against the image. - /// The . - private static Image PerformAction(Image source, bool clone, Action, ImageBase> action) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Image transformedImage = clone - ? new Image(source) - : new Image(); - - // Several properties still require copying - if (!clone) - { - transformedImage.CopyProperties(source); - } - - action(source, transformedImage); - - for (int i = 0; i < source.Frames.Count; i++) - { - ImageFrame sourceFrame = source.Frames[i]; - ImageFrame tranformedFrame = clone - ? new ImageFrame(sourceFrame) - : new ImageFrame { FrameDelay = sourceFrame.FrameDelay }; - - action(sourceFrame, tranformedFrame); - - if (!clone) - { - transformedImage.Frames.Add(tranformedFrame); - } - else - { - transformedImage.Frames[i] = tranformedFrame; - } - } - - source = transformedImage; - return source; - } - } -} diff --git a/src/ImageSharp46/Image/ImageProperty.cs b/src/ImageSharp46/Image/ImageProperty.cs deleted file mode 100644 index 7fda749e9..000000000 --- a/src/ImageSharp46/Image/ImageProperty.cs +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// Stores meta information about a image, like the name of the author, - /// the copyright information, the date, where the image was created - /// or some other information. - /// - public class ImageProperty : IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The name of the property. - /// The value of the property. - public ImageProperty(string name, string value) - { - Guard.NotNullOrEmpty(name, nameof(name)); - - this.Name = name; - this.Value = value; - } - - /// - /// Gets the name of this indicating which kind of - /// information this property stores. - /// - /// - /// Typical properties are the author, copyright - /// information or other meta information. - /// - public string Name { get; } - - /// - /// Gets the value of this . - /// - public string Value { get; } - - /// - /// Compares two objects. The result specifies whether the values - /// of the or properties of the two - /// objects are equal. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(ImageProperty left, ImageProperty right) - { - return Equals(left, right); - } - - /// - /// Compares two objects. The result specifies whether the values - /// of the or properties of the two - /// objects are unequal. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(ImageProperty left, ImageProperty right) - { - return !Equals(left, right); - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// - /// The object to compare with the current instance. - /// - /// - /// true if and this instance are the same type and represent the - /// same value; otherwise, false. - /// - public override bool Equals(object obj) - { - ImageProperty other = obj as ImageProperty; - - return this.Equals(other); - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.Name.GetHashCode(); - if (this.Value != null) - { - hashCode = (hashCode * 397) ^ this.Value.GetHashCode(); - } - - return hashCode; - } - } - - /// - /// Returns the fully qualified type name of this instance. - /// - /// - /// A containing a fully qualified type name. - /// - public override string ToString() - { - return $"ImageProperty [ Name={this.Name}, Value={this.Value} ]"; - } - - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// - /// True if the current object is equal to the parameter; otherwise, false. - /// - /// An object to compare with this object. - public bool Equals(ImageProperty other) - { - if (ReferenceEquals(other, null)) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - return this.Name.Equals(other.Name) && Equals(this.Value, other.Value); - } - } -} diff --git a/src/ImageSharp46/Image/PixelAccessor.cs b/src/ImageSharp46/Image/PixelAccessor.cs deleted file mode 100644 index fec50b972..000000000 --- a/src/ImageSharp46/Image/PixelAccessor.cs +++ /dev/null @@ -1,398 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - - /// - /// Provides per-pixel access to generic pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public unsafe class PixelAccessor : IDisposable - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The pointer to the pixel buffer. - /// - private IntPtr dataPointer; - - /// - /// The position of the first pixel in the image. - /// - private byte* pixelsBase; - - /// - /// Provides a way to access the pixels from unmanaged memory. - /// - private GCHandle pixelsHandle; - - /// - /// A value indicating whether this instance of the given entity has been disposed. - /// - /// if this instance has been disposed; otherwise, . - /// - /// If the entity is disposed, it must not be disposed a second time. The isDisposed field is set the first time the entity - /// is disposed. If the isDisposed field is true, then the Dispose() method will not dispose again. This help not to prolong the entity's - /// life in the Garbage Collector. - /// - private bool isDisposed; - - /// - /// Initializes a new instance of the class. - /// - /// The image to provide pixel access for. - public PixelAccessor(ImageBase image) - { - Guard.NotNull(image, nameof(image)); - Guard.MustBeGreaterThan(image.Width, 0, "image width"); - Guard.MustBeGreaterThan(image.Height, 0, "image height"); - - this.Width = image.Width; - this.Height = image.Height; - this.pixelsHandle = GCHandle.Alloc(image.Pixels, GCHandleType.Pinned); - this.dataPointer = this.pixelsHandle.AddrOfPinnedObject(); - this.pixelsBase = (byte*)this.dataPointer.ToPointer(); - this.PixelSize = Unsafe.SizeOf(); - this.RowStride = this.Width * this.PixelSize; - } - - /// - /// Finalizes an instance of the class. - /// - ~PixelAccessor() - { - this.Dispose(); - } - - /// - /// Gets the pointer to the pixel buffer. - /// - public IntPtr DataPointer => this.dataPointer; - - /// - /// Gets the size of a single pixel in the number of bytes. - /// - public int PixelSize { get; } - - /// - /// Gets the width of one row in the number of bytes. - /// - public int RowStride { get; } - - /// - /// Gets the width of the image. - /// - public int Width { get; } - - /// - /// Gets the height of the image. - /// - public int Height { get; } - - /// - /// Gets or sets the pixel at the specified position. - /// - /// The x-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel. - /// The y-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel. - /// The at the specified position. - public TColor this[int x, int y] - { - get { return Unsafe.Read(this.pixelsBase + (((y * this.Width) + x) * Unsafe.SizeOf())); } - set { Unsafe.Write(this.pixelsBase + (((y * this.Width) + x) * Unsafe.SizeOf()), value); } - } - - /// - /// Copies a block of pixels at the specified position. - /// - /// The x-coordinate of the source image. - /// The y-coordinate of the source image. - /// The target pixel buffer accessor. - /// The x-coordinate of the target image. - /// The y-coordinate of the target image. - /// The number of pixels to copy - public void CopyBlock(int sourceX, int sourceY, PixelAccessor target, int targetX, int targetY, int pixelCount) - { - int size = Unsafe.SizeOf(); - byte* sourcePtr = this.pixelsBase + (((sourceY * this.Width) + sourceX) * size); - byte* targetPtr = target.pixelsBase + (((targetY * target.Width) + targetX) * size); - uint byteCount = (uint)(pixelCount * size); - - Unsafe.CopyBlock(targetPtr, sourcePtr, byteCount); - } - - /// - /// Copies an entire image. - /// - /// The target pixel buffer accessor. - public void CopyImage(PixelAccessor target) - { - this.CopyBlock(0, 0, target, 0, 0, target.Width * target.Height); - } - - /// - /// Copied a row of pixels from the image. - /// - /// The row. - /// The target row index. - /// - /// Thrown when an unsupported component order value is passed. - /// - public void CopyFrom(PixelRow row, int targetY) - { - switch (row.ComponentOrder) - { - case ComponentOrder.ZYX: - this.CopyFromZYX(row, targetY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.ZYXW: - this.CopyFromZYXW(row, targetY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.XYZ: - this.CopyFromXYZ(row, targetY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.XYZW: - this.CopyFromXYZW(row, targetY, Math.Min(row.Width, this.Width)); - break; - default: - throw new NotSupportedException(); - } - } - - /// - /// Copied a row of pixels to the image. - /// - /// The row. - /// The source row index. - /// - /// Thrown when an unsupported component order value is passed. - /// - public void CopyTo(PixelRow row, int sourceY) - { - switch (row.ComponentOrder) - { - case ComponentOrder.ZYX: - this.CopyToZYX(row, sourceY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.ZYXW: - this.CopyToZYXW(row, sourceY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.XYZ: - this.CopyToXYZ(row, sourceY, Math.Min(row.Width, this.Width)); - break; - case ComponentOrder.XYZW: - this.CopyToXYZW(row, sourceY, Math.Min(row.Width, this.Width)); - break; - default: - throw new NotSupportedException(); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - if (this.isDisposed) - { - return; - } - - if (this.pixelsHandle.IsAllocated) - { - this.pixelsHandle.Free(); - } - - this.dataPointer = IntPtr.Zero; - this.pixelsBase = null; - - // Note disposing is done. - this.isDisposed = true; - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SuppressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - /// - /// Copies from a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyFromZYX(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, 255); - Unsafe.Write(destination, packed); - - source += 3; - destination += size; - } - } - - /// - /// Copies from a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyFromZYXW(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*(source + 2), *(source + 1), *source, *(source + 3)); - Unsafe.Write(destination, packed); - - source += 4; - destination += size; - } - } - - /// - /// Copies from a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyFromXYZ(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), 255); - Unsafe.Write(destination, packed); - - source += 3; - destination += size; - } - } - - /// - /// Copies from a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyFromXYZW(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - TColor packed = default(TColor); - int size = Unsafe.SizeOf(); - - for (int x = 0; x < width; x++) - { - packed.PackFromBytes(*source, *(source + 1), *(source + 2), *(source + 3)); - Unsafe.Write(destination, packed); - - source += 4; - destination += size; - } - } - - /// - /// Copies to a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyToZYX(PixelRow row, int sourceY, int width) - { - int offset = 0; - for (int x = 0; x < width; x++) - { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.ZYX); - offset += 3; - } - } - - /// - /// Copies to a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyToZYXW(PixelRow row, int sourceY, int width) - { - int offset = 0; - for (int x = 0; x < width; x++) - { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.ZYXW); - offset += 4; - } - } - - /// - /// Copies to a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyToXYZ(PixelRow row, int sourceY, int width) - { - int offset = 0; - for (int x = 0; x < width; x++) - { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.XYZ); - offset += 3; - } - } - - /// - /// Copies to a row in format. - /// - /// The row. - /// The target row index. - /// The width. - protected virtual void CopyToXYZW(PixelRow row, int sourceY, int width) - { - int offset = 0; - for (int x = 0; x < width; x++) - { - this[x, sourceY].ToBytes(row.Bytes, offset, ComponentOrder.XYZW); - offset += 4; - } - } - - /// - /// Gets the pointer at the specified row. - /// - /// The target row index. - /// - /// The . - /// - protected byte* GetRowPointer(int targetY) - { - return this.pixelsBase + ((targetY * this.Width) * Unsafe.SizeOf()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Image/PixelRow.cs b/src/ImageSharp46/Image/PixelRow.cs deleted file mode 100644 index 4682aaaac..000000000 --- a/src/ImageSharp46/Image/PixelRow.cs +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.IO; - using System.Runtime.InteropServices; - - /// - /// Represents a row of generic pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public sealed unsafe class PixelRow : IDisposable - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Provides a way to access the pixels from unmanaged memory. - /// - private readonly GCHandle pixelsHandle; - - /// - /// The pointer to the pixel buffer. - /// - private IntPtr dataPointer; - - /// - /// A value indicating whether this instance of the given entity has been disposed. - /// - /// if this instance has been disposed; otherwise, . - /// - /// If the entity is disposed, it must not be disposed a second time. The isDisposed field is set the first time the entity - /// is disposed. If the isDisposed field is true, then the Dispose() method will not dispose again. This help not to prolong the entity's - /// life in the Garbage Collector. - /// - private bool isDisposed; - - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The component order. - public PixelRow(int width, ComponentOrder componentOrder) - : this(width, componentOrder, 0) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The component order. - /// The number of bytes to pad each row. - public PixelRow(int width, ComponentOrder componentOrder, int padding) - { - this.Width = width; - this.ComponentOrder = componentOrder; - this.Bytes = new byte[(width * GetComponentCount(componentOrder)) + padding]; - this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned); - - // TODO: Why is Resharper warning us about an impure method call? - this.dataPointer = this.pixelsHandle.AddrOfPinnedObject(); - this.PixelBase = (byte*)this.dataPointer.ToPointer(); - } - - /// - /// Finalizes an instance of the class. - /// - ~PixelRow() - { - this.Dispose(); - } - - /// - /// Gets the data in bytes. - /// - public byte[] Bytes { get; } - - /// - /// Gets the pointer to the pixel buffer. - /// - public IntPtr DataPointer => this.dataPointer; - - /// - /// Gets the data pointer. - /// - public byte* PixelBase { get; private set; } - - /// - /// Gets the component order. - /// - public ComponentOrder ComponentOrder { get; } - - /// - /// Gets the width. - /// - public int Width { get; } - - /// - /// Reads the stream to the row. - /// - /// The stream. - public void Read(Stream stream) - { - stream.Read(this.Bytes, 0, this.Bytes.Length); - } - - /// - /// Writes the row to the stream. - /// - /// The stream. - public void Write(Stream stream) - { - stream.Write(this.Bytes, 0, this.Bytes.Length); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - if (this.isDisposed) - { - return; - } - - if (this.PixelBase == null) - { - return; - } - - if (this.pixelsHandle.IsAllocated) - { - this.pixelsHandle.Free(); - } - - this.dataPointer = IntPtr.Zero; - this.PixelBase = null; - - this.isDisposed = true; - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SuppressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - /// - /// Gets component count for the given order. - /// - /// The component order. - /// - /// The . - /// - /// - /// Thrown if an invalid order is given. - /// - private static int GetComponentCount(ComponentOrder componentOrder) - { - switch (componentOrder) - { - case ComponentOrder.ZYX: - case ComponentOrder.XYZ: - return 3; - case ComponentOrder.ZYXW: - case ComponentOrder.XYZW: - return 4; - } - - throw new NotSupportedException(); - } - } -} diff --git a/src/ImageSharp46/ImageProcessor.cs b/src/ImageSharp46/ImageProcessor.cs deleted file mode 100644 index 17395218d..000000000 --- a/src/ImageSharp46/ImageProcessor.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Threading.Tasks; - - /// - /// Allows the application of processors to images. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class ImageProcessor : IImageProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.Instance.ParallelOptions; - - /// - public virtual bool Compand { get; set; } = false; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/ImageSharp46.csproj b/src/ImageSharp46/ImageSharp46.csproj deleted file mode 100644 index fdb1b7293..000000000 --- a/src/ImageSharp46/ImageSharp46.csproj +++ /dev/null @@ -1,403 +0,0 @@ - - - - - Debug - AnyCPU - {FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1} - Library - Properties - ImageSharp - ImageSharp - v4.6.1 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - ..\..\packages\Microsoft.Win32.Primitives.4.0.1\lib\net46\Microsoft.Win32.Primitives.dll - True - - - - ..\..\packages\System.AppContext.4.1.0\lib\net46\System.AppContext.dll - True - - - ..\..\packages\System.Buffers.4.0.0\lib\netstandard1.1\System.Buffers.dll - True - - - - ..\..\packages\System.Console.4.0.0\lib\net46\System.Console.dll - True - - - - ..\..\packages\System.Diagnostics.DiagnosticSource.4.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll - True - - - ..\..\packages\System.Globalization.Calendars.4.0.1\lib\net46\System.Globalization.Calendars.dll - True - - - ..\..\packages\System.IO.Compression.4.1.0\lib\net46\System.IO.Compression.dll - True - - - - ..\..\packages\System.IO.Compression.ZipFile.4.0.1\lib\net46\System.IO.Compression.ZipFile.dll - True - - - ..\..\packages\System.IO.FileSystem.4.0.1\lib\net46\System.IO.FileSystem.dll - True - - - ..\..\packages\System.IO.FileSystem.Primitives.4.0.1\lib\net46\System.IO.FileSystem.Primitives.dll - True - - - ..\..\packages\System.Net.Http.4.1.0\lib\net46\System.Net.Http.dll - True - - - ..\..\packages\System.Net.Sockets.4.1.0\lib\net46\System.Net.Sockets.dll - True - - - - ..\..\packages\System.Numerics.Vectors.4.1.1\lib\net46\System.Numerics.Vectors.dll - True - - - ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.0.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - True - - - ..\..\packages\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll - True - - - ..\..\packages\System.Security.Cryptography.Algorithms.4.2.0\lib\net461\System.Security.Cryptography.Algorithms.dll - True - - - ..\..\packages\System.Security.Cryptography.Encoding.4.0.0\lib\net46\System.Security.Cryptography.Encoding.dll - True - - - ..\..\packages\System.Security.Cryptography.Primitives.4.0.0\lib\net46\System.Security.Cryptography.Primitives.dll - True - - - ..\..\packages\System.Security.Cryptography.X509Certificates.4.1.0\lib\net461\System.Security.Cryptography.X509Certificates.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageSharp46/Numerics/Ellipse.cs b/src/ImageSharp46/Numerics/Ellipse.cs deleted file mode 100644 index f464c4b26..000000000 --- a/src/ImageSharp46/Numerics/Ellipse.cs +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - public struct Ellipse : IEquatable - { - /// - /// The center point. - /// - private Point center; - - /// - /// Represents a that has X and Y values set to zero. - /// - public static readonly Ellipse Empty = default(Ellipse); - - public Ellipse(Point center, float radiusX, float radiusY) - { - this.center = center; - this.RadiusX = radiusX; - this.RadiusY = radiusY; - } - - /// - /// Gets the x-radius of this . - /// - public float RadiusX { get; } - - /// - /// Gets the y-radius of this . - /// - public float RadiusY { get; } - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Ellipse left, Ellipse right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Ellipse left, Ellipse right) - { - return !left.Equals(right); - } - - /// - /// Returns the center point of the given - /// - /// The ellipse - /// - public static Vector2 Center(Ellipse ellipse) - { - return new Vector2(ellipse.center.X, ellipse.center.Y); - } - - /// - /// Determines if the specfied point is contained within the rectangular region defined by - /// this . - /// - /// The x-coordinate of the given point. - /// The y-coordinate of the given point. - /// The - public bool Contains(int x, int y) - { - if (this.RadiusX <= 0 || this.RadiusY <= 0) - { - return false; - } - - // TODO: SIMD? - // This is a more general form of the circle equation - // X^2/a^2 + Y^2/b^2 <= 1 - Point normalized = new Point(x - this.center.X, y - this.center.Y); - int nX = normalized.X; - int nY = normalized.Y; - - return ((double)(nX * nX) / (this.RadiusX * this.RadiusX)) - + ((double)(nY * nY) / (this.RadiusY * this.RadiusY)) - <= 1.0; - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Ellipse [ Empty ]"; - } - - return - $"Ellipse [ RadiusX={this.RadiusX}, RadiusY={this.RadiusX}, Centre={this.center.X},{this.center.Y} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Ellipse) - { - return this.Equals((Ellipse)obj); - } - - return false; - } - - /// - public bool Equals(Ellipse other) - { - return this.center.Equals(other.center) - && this.RadiusX.Equals(other.RadiusX) - && this.RadiusY.Equals(other.RadiusY); - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(Ellipse ellipse) - { - unchecked - { - int hashCode = ellipse.center.GetHashCode(); - hashCode = (hashCode * 397) ^ ellipse.RadiusX.GetHashCode(); - hashCode = (hashCode * 397) ^ ellipse.RadiusY.GetHashCode(); - return hashCode; - } - } - } -} diff --git a/src/ImageSharp46/Numerics/LongRational.cs b/src/ImageSharp46/Numerics/LongRational.cs deleted file mode 100644 index f56abc289..000000000 --- a/src/ImageSharp46/Numerics/LongRational.cs +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Globalization; - using System.Text; - - /// - /// Represents a number that can be expressed as a fraction - /// - /// - /// This is a very simplified implementation of a rational number designed for use with metadata only. - /// - internal struct LongRational : IEquatable - { - /// - /// Initializes a new instance of the struct. - /// - /// - /// The number above the line in a vulgar fraction showing how many of the parts - /// indicated by the denominator are taken. - /// - /// - /// The number below the line in a vulgar fraction; a divisor. - /// - public LongRational(long numerator, long denominator) - : this(numerator, denominator, false) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The number above the line in a vulgar fraction showing how many of the parts - /// indicated by the denominator are taken. - /// - /// - /// The number below the line in a vulgar fraction; a divisor. - /// - /// - /// Whether to attempt to simplify the fractional parts. - /// - public LongRational(long numerator, long denominator, bool simplify) - : this() - { - this.Numerator = numerator; - this.Denominator = denominator; - - if (simplify) - { - this.Simplify(); - } - } - - /// - /// Initializes a new instance of the struct. - /// - /// The to create the instance from. - /// Whether to use the best possible precision when parsing the value. - public LongRational(double value, bool bestPrecision) - : this() - { - if (double.IsNaN(value)) - { - this.Numerator = this.Denominator = 0; - return; - } - - if (double.IsPositiveInfinity(value)) - { - this.Numerator = 1; - this.Denominator = 0; - return; - } - - if (double.IsNegativeInfinity(value)) - { - this.Numerator = -1; - this.Denominator = 0; - return; - } - - this.Numerator = 1; - this.Denominator = 1; - - double val = Math.Abs(value); - double df = this.Numerator / (double)this.Denominator; - double epsilon = bestPrecision ? double.Epsilon : .000001; - - while (Math.Abs(df - val) > epsilon) - { - if (df < val) - { - this.Numerator++; - } - else - { - this.Denominator++; - this.Numerator = (int)(val * this.Denominator); - } - - df = this.Numerator / (double)this.Denominator; - } - - if (value < 0.0) - { - this.Numerator *= -1; - } - - this.Simplify(); - } - - /// - /// Gets the numerator of a number. - /// - public long Numerator - { - get; - private set; - } - - /// - /// Gets the denominator of a number. - /// - public long Denominator - { - get; - private set; - } - - /// - /// Gets a value indicating whether this instance is indeterminate. - /// - public bool IsIndeterminate - { - get - { - if (this.Denominator != 0) - { - return false; - } - - return this.Numerator == 0; - } - } - - /// - /// Gets a value indicating whether this instance is an integer (n, 1) - /// - public bool IsInteger => this.Denominator == 1; - - /// - /// Gets a value indicating whether this instance is equal to negative infinity (-1, 0) - /// - public bool IsNegativeInfinity - { - get - { - if (this.Denominator != 0) - { - return false; - } - - return this.Numerator == -1; - } - } - - /// - /// Gets a value indicating whether this instance is equal to positive infinity (1, 0) - /// - public bool IsPositiveInfinity - { - get - { - if (this.Denominator != 0) - { - return false; - } - - return this.Numerator == 1; - } - } - - /// - /// Gets a value indicating whether this instance is equal to 0 (0, 1) - /// - public bool IsZero - { - get - { - if (this.Denominator != 1) - { - return false; - } - - return this.Numerator == 0; - } - } - - /// - public bool Equals(LongRational other) - { - if (this.Denominator == other.Denominator) - { - return this.Numerator == other.Numerator; - } - - if (this.Numerator == 0 && this.Denominator == 0) - { - return other.Numerator == 0 && other.Denominator == 0; - } - - if (other.Numerator == 0 && other.Denominator == 0) - { - return this.Numerator == 0 && this.Denominator == 0; - } - - return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator); - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - return this.ToString(CultureInfo.InvariantCulture); - } - - /// - /// Converts the numeric value of this instance to its equivalent string representation using - /// the specified culture-specific format information. - /// - /// - /// An object that supplies culture-specific formatting information. - /// - /// The - public string ToString(IFormatProvider provider) - { - if (this.IsIndeterminate) - { - return "[ Indeterminate ]"; - } - - if (this.IsPositiveInfinity) - { - return "[ PositiveInfinity ]"; - } - - if (this.IsNegativeInfinity) - { - return "[ NegativeInfinity ]"; - } - - if (this.IsZero) - { - return "0"; - } - - if (this.IsInteger) - { - return this.Numerator.ToString(provider); - } - - StringBuilder sb = new StringBuilder(); - sb.Append(this.Numerator.ToString(provider)); - sb.Append("/"); - sb.Append(this.Denominator.ToString(provider)); - return sb.ToString(); - } - - /// - /// Finds the greatest common divisor of two values. - /// - /// The first value - /// The second value - /// The - private static long GreatestCommonDivisor(long left, long right) - { - return right == 0 ? left : GreatestCommonDivisor(right, left % right); - } - - /// - /// Simplifies the - /// - private void Simplify() - { - if (this.IsIndeterminate) - { - return; - } - - if (this.IsNegativeInfinity) - { - return; - } - - if (this.IsPositiveInfinity) - { - return; - } - - if (this.IsInteger) - { - return; - } - - if (this.IsZero) - { - return; - } - - if (this.Numerator == 0) - { - this.Denominator = 0; - return; - } - - if (this.Numerator == this.Denominator) - { - this.Numerator = 1; - this.Denominator = 1; - } - - long gcd = GreatestCommonDivisor(Math.Abs(this.Numerator), Math.Abs(this.Denominator)); - if (gcd > 1) - { - this.Numerator = this.Numerator / gcd; - this.Denominator = this.Denominator / gcd; - } - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(LongRational rational) - { - return ((rational.Numerator * 397) ^ rational.Denominator).GetHashCode(); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Numerics/Point.cs b/src/ImageSharp46/Numerics/Point.cs deleted file mode 100644 index 3cd47659c..000000000 --- a/src/ImageSharp46/Numerics/Point.cs +++ /dev/null @@ -1,282 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - using System.Runtime.CompilerServices; - - /// - /// Represents an ordered pair of integer x- and y-coordinates that defines a point in - /// a two-dimensional plane. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public struct Point : IEquatable - { - /// - /// Represents a that has X and Y values set to zero. - /// - public static readonly Point Empty = default(Point); - - /// - /// Initializes a new instance of the struct. - /// - /// The horizontal position of the point. - /// The vertical position of the point. - public Point(int x, int y) - : this() - { - this.X = x; - this.Y = y; - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector representing the width and height. - /// - public Point(Vector2 vector) - { - this.X = (int)Math.Round(vector.X); - this.Y = (int)Math.Round(vector.Y); - } - - /// - /// Gets or sets the x-coordinate of this . - /// - public int X { get; set; } - - /// - /// Gets or sets the y-coordinate of this . - /// - public int Y { get; set; } - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Computes the sum of adding two points. - /// - /// The point on the left hand of the operand. - /// The point on the right hand of the operand. - /// - /// The - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator +(Point left, Point right) - { - return new Point(left.X + right.X, left.Y + right.Y); - } - - /// - /// Computes the difference left by subtracting one point from another. - /// - /// The point on the left hand of the operand. - /// The point on the right hand of the operand. - /// - /// The - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator -(Point left, Point right) - { - return new Point(left.X - right.X, left.Y - right.Y); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Point left, Point right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(Point left, Point right) - { - return !left.Equals(right); - } - - /// - /// Creates a rotation matrix for the given point and angle. - /// - /// The origin point to rotate around - /// Rotation in degrees - /// The rotation - public static Matrix3x2 CreateRotation(Point origin, float degrees) - { - float radians = ImageMaths.DegreesToRadians(degrees); - return Matrix3x2.CreateRotation(radians, new Vector2(origin.X, origin.Y)); - } - - /// - /// Rotates a point around a given a rotation matrix. - /// - /// The point to rotate - /// Rotation matrix used - /// The rotated - public static Point Rotate(Point point, Matrix3x2 rotation) - { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); - } - - /// - /// Rotates a point around a given origin by the specified angle in degrees. - /// - /// The point to rotate - /// The center point to rotate around. - /// The angle in degrees. - /// The rotated - public static Point Rotate(Point point, Point origin, float degrees) - { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), CreateRotation(origin, degrees))); - } - - /// - /// Creates a skew matrix for the given point and angle. - /// - /// The origin point to rotate around - /// The x-angle in degrees. - /// The y-angle in degrees. - /// The rotation - public static Matrix3x2 CreateSkew(Point origin, float degreesX, float degreesY) - { - float radiansX = ImageMaths.DegreesToRadians(degreesX); - float radiansY = ImageMaths.DegreesToRadians(degreesY); - return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(origin.X, origin.Y)); - } - - /// - /// Skews a point using a given a skew matrix. - /// - /// The point to rotate - /// Rotation matrix used - /// The rotated - public static Point Skew(Point point, Matrix3x2 skew) - { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), skew)); - } - - /// - /// Skews a point around a given origin by the specified angles in degrees. - /// - /// The point to skew. - /// The center point to rotate around. - /// The x-angle in degrees. - /// The y-angle in degrees. - /// The skewed - public static Point Skew(Point point, Point origin, float degreesX, float degreesY) - { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), CreateSkew(origin, degreesX, degreesY))); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - public Vector2 ToVector2() - { - return new Vector2(this.X, this.Y); - } - - /// - /// Translates this by the specified amount. - /// - /// The amount to offset the x-coordinate. - /// The amount to offset the y-coordinate. - public void Offset(int dx, int dy) - { - this.X += dx; - this.Y += dy; - } - - /// - /// Translates this by the specified amount. - /// - /// The used offset this . - public void Offset(Point p) - { - this.Offset(p.X, p.Y); - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Point [ Empty ]"; - } - - return $"Point [ X={this.X}, Y={this.Y} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Point) - { - return this.Equals((Point)obj); - } - - return false; - } - - /// - public bool Equals(Point other) - { - return this.X == other.X && this.Y == other.Y; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(Point point) - { - return point.X ^ point.Y; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Numerics/Rational.cs b/src/ImageSharp46/Numerics/Rational.cs deleted file mode 100644 index d219a5469..000000000 --- a/src/ImageSharp46/Numerics/Rational.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Globalization; - - /// - /// Represents a number that can be expressed as a fraction. - /// - /// - /// This is a very simplified implementation of a rational number designed for use with metadata only. - /// - public struct Rational : IEquatable - { - /// - /// Initializes a new instance of the struct. - /// - /// The to create the rational from. - public Rational(uint value) - : this(value, 1) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken. - /// The number below the line in a vulgar fraction; a divisor. - public Rational(uint numerator, uint denominator) - : this(numerator, denominator, true) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken. - /// The number below the line in a vulgar fraction; a divisor. - /// Specified if the rational should be simplified. - public Rational(uint numerator, uint denominator, bool simplify) - { - LongRational rational = new LongRational(numerator, denominator, simplify); - - this.Numerator = (uint)rational.Numerator; - this.Denominator = (uint)rational.Denominator; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The to create the instance from. - public Rational(double value) - : this(value, false) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The to create the instance from. - /// Whether to use the best possible precision when parsing the value. - public Rational(double value, bool bestPrecision) - { - LongRational rational = new LongRational(Math.Abs(value), bestPrecision); - - this.Numerator = (uint)rational.Numerator; - this.Denominator = (uint)rational.Denominator; - } - - /// - /// Gets the numerator of a number. - /// - public uint Numerator { get; } - - /// - /// Gets the denominator of a number. - /// - public uint Denominator { get; } - - /// - /// Determines whether the specified instances are considered equal. - /// - /// The first to compare. - /// The second to compare. - /// The - public static bool operator ==(Rational left, Rational right) - { - return Rational.Equals(left, right); - } - - /// - /// Determines whether the specified instances are not considered equal. - /// - /// The first to compare. - /// The second to compare. - /// The - public static bool operator !=(Rational left, Rational right) - { - return !Rational.Equals(left, right); - } - - /// - /// Converts the specified to an instance of this type. - /// - /// The to convert to an instance of this type. - /// - /// The . - /// - public static Rational FromDouble(double value) - { - return new Rational(value, false); - } - - /// - /// Converts the specified to an instance of this type. - /// - /// The to convert to an instance of this type. - /// Whether to use the best possible precision when parsing the value. - /// - /// The . - /// - public static Rational FromDouble(double value, bool bestPrecision) - { - return new Rational(value, bestPrecision); - } - - /// - public override bool Equals(object obj) - { - if (obj is Rational) - { - return this.Equals((Rational)obj); - } - - return false; - } - - /// - public bool Equals(Rational other) - { - LongRational left = new LongRational(this.Numerator, this.Denominator); - LongRational right = new LongRational(other.Numerator, other.Denominator); - - return left.Equals(right); - } - - /// - public override int GetHashCode() - { - LongRational self = new LongRational(this.Numerator, this.Denominator); - return self.GetHashCode(); - } - - /// - /// Converts a rational number to the nearest . - /// - /// - /// The . - /// - public double ToDouble() - { - return this.Numerator / (double)this.Denominator; - } - - /// - public override string ToString() - { - return this.ToString(CultureInfo.InvariantCulture); - } - - /// - /// Converts the numeric value of this instance to its equivalent string representation using - /// the specified culture-specific format information. - /// - /// - /// An object that supplies culture-specific formatting information. - /// - /// The - public string ToString(IFormatProvider provider) - { - LongRational rational = new LongRational(this.Numerator, this.Denominator); - return rational.ToString(provider); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Numerics/Rectangle.cs b/src/ImageSharp46/Numerics/Rectangle.cs deleted file mode 100644 index fb623c2eb..000000000 --- a/src/ImageSharp46/Numerics/Rectangle.cs +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Stores a set of four integers that represent the location and size of a rectangle. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public struct Rectangle : IEquatable - { - /// - /// Represents a that has X, Y, Width, and Height values set to zero. - /// - public static readonly Rectangle Empty = default(Rectangle); - - /// - /// The backing vector for SIMD support. - /// - private Vector4 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The horizontal position of the rectangle. - /// The vertical position of the rectangle. - /// The width of the rectangle. - /// The height of the rectangle. - public Rectangle(int x, int y, int width, int height) - { - this.backingVector = new Vector4(x, y, width, height); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The which specifies the rectangles point in a two-dimensional plane. - /// - /// - /// The which specifies the rectangles height and width. - /// - public Rectangle(Point point, Size size) - { - this.backingVector = new Vector4(point.X, point.Y, size.Width, size.Height); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The vector. - public Rectangle(Vector4 vector) - { - this.backingVector = vector; - } - - /// - /// Gets or sets the x-coordinate of this . - /// - public int X - { - get - { - return (int)this.backingVector.X; - } - - set - { - this.backingVector.X = value; - } - } - - /// - /// Gets or sets the y-coordinate of this . - /// - public int Y - { - get - { - return (int)this.backingVector.Y; - } - - set - { - this.backingVector.Y = value; - } - } - - /// - /// Gets or sets the width of this . - /// - public int Width - { - get - { - return (int)this.backingVector.Z; - } - - set - { - this.backingVector.Z = value; - } - } - - /// - /// Gets or sets the height of this . - /// - public int Height - { - get - { - return (int)this.backingVector.W; - } - - set - { - this.backingVector.W = value; - } - } - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Gets the y-coordinate of the top edge of this . - /// - public int Top => this.Y; - - /// - /// Gets the x-coordinate of the right edge of this . - /// - public int Right => this.X + this.Width; - - /// - /// Gets the y-coordinate of the bottom edge of this . - /// - public int Bottom => this.Y + this.Height; - - /// - /// Gets the x-coordinate of the left edge of this . - /// - public int Left => this.X; - - /// - /// Computes the sum of adding two rectangles. - /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static Rectangle operator +(Rectangle left, Rectangle right) - { - return new Rectangle(left.backingVector + right.backingVector); - } - - /// - /// Computes the difference left by subtracting one rectangle from another. - /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static Rectangle operator -(Rectangle left, Rectangle right) - { - return new Rectangle(left.backingVector - right.backingVector); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Rectangle left, Rectangle right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Rectangle left, Rectangle right) - { - return !left.Equals(right); - } - - /// - /// Determines if the specfied point is contained within the rectangular region defined by - /// this . - /// - /// The x-coordinate of the given point. - /// The y-coordinate of the given point. - /// The - public bool Contains(int x, int y) - { - // TODO: SIMD? - return this.X <= x - && x < this.Right - && this.Y <= y - && y < this.Bottom; - } - - /// - /// Returns the center point of the given - /// - /// The rectangle - /// - public static Point Center(Rectangle rectangle) - { - return new Point(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Rectangle [ Empty ]"; - } - - return - $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Rectangle) - { - return this.Equals((Rectangle)obj); - } - - return false; - } - - /// - public bool Equals(Rectangle other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(Rectangle rectangle) - { - return rectangle.backingVector.GetHashCode(); - } - } -} diff --git a/src/ImageSharp46/Numerics/SignedRational.cs b/src/ImageSharp46/Numerics/SignedRational.cs deleted file mode 100644 index bd2213dce..000000000 --- a/src/ImageSharp46/Numerics/SignedRational.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Globalization; - - /// - /// Represents a number that can be expressed as a fraction. - /// - /// - /// This is a very simplified implementation of a rational number designed for use with metadata only. - /// - public struct SignedRational : IEquatable - { - /// - /// Initializes a new instance of the struct. - /// - /// The to create the rational from. - public SignedRational(int value) - : this(value, 1) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken. - /// The number below the line in a vulgar fraction; a divisor. - public SignedRational(int numerator, int denominator) - : this(numerator, denominator, true) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken. - /// The number below the line in a vulgar fraction; a divisor. - /// Specified if the rational should be simplified. - public SignedRational(int numerator, int denominator, bool simplify) - { - LongRational rational = new LongRational(numerator, denominator, simplify); - - this.Numerator = (int)rational.Numerator; - this.Denominator = (int)rational.Denominator; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The to create the instance from. - public SignedRational(double value) - : this(value, false) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// The to create the instance from. - /// Whether to use the best possible precision when parsing the value. - public SignedRational(double value, bool bestPrecision) - { - LongRational rational = new LongRational(value, bestPrecision); - - this.Numerator = (int)rational.Numerator; - this.Denominator = (int)rational.Denominator; - } - - /// - /// Gets the numerator of a number. - /// - public int Numerator { get; } - - /// - /// Gets the denominator of a number. - /// - public int Denominator { get; } - - /// - /// Determines whether the specified instances are considered equal. - /// - /// The first to compare. - /// The second to compare. - /// The - public static bool operator ==(SignedRational left, SignedRational right) - { - return SignedRational.Equals(left, right); - } - - /// - /// Determines whether the specified instances are not considered equal. - /// - /// The first to compare. - /// The second to compare. - /// The - public static bool operator !=(SignedRational left, SignedRational right) - { - return !SignedRational.Equals(left, right); - } - - /// - /// Converts the specified to an instance of this type. - /// - /// The to convert to an instance of this type. - /// - /// The . - /// - public static SignedRational FromDouble(double value) - { - return new SignedRational(value, false); - } - - /// - /// Converts the specified to an instance of this type. - /// - /// The to convert to an instance of this type. - /// Whether to use the best possible precision when parsing the value. - /// - /// The . - /// - public static SignedRational FromDouble(double value, bool bestPrecision) - { - return new SignedRational(value, bestPrecision); - } - - /// - public override bool Equals(object obj) - { - if (obj is SignedRational) - { - return this.Equals((SignedRational)obj); - } - - return false; - } - - /// - public bool Equals(SignedRational other) - { - LongRational left = new LongRational(this.Numerator, this.Denominator); - LongRational right = new LongRational(other.Numerator, other.Denominator); - - return left.Equals(right); - } - - /// - public override int GetHashCode() - { - LongRational self = new LongRational(this.Numerator, this.Denominator); - return self.GetHashCode(); - } - - /// - /// Converts a rational number to the nearest . - /// - /// - /// The . - /// - public double ToDouble() - { - return this.Numerator / (double)this.Denominator; - } - - /// - public override string ToString() - { - return this.ToString(CultureInfo.InvariantCulture); - } - - /// - /// Converts the numeric value of this instance to its equivalent string representation using - /// the specified culture-specific format information. - /// - /// - /// An object that supplies culture-specific formatting information. - /// - /// The - public string ToString(IFormatProvider provider) - { - LongRational rational = new LongRational(this.Numerator, this.Denominator); - return rational.ToString(provider); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Numerics/Size.cs b/src/ImageSharp46/Numerics/Size.cs deleted file mode 100644 index bae645ac8..000000000 --- a/src/ImageSharp46/Numerics/Size.cs +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.ComponentModel; - using System.Runtime.CompilerServices; - - /// - /// Stores an ordered pair of integers, which specify a height and width. - /// - /// - /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, - /// as it avoids the need to create new values for modification operations. - /// - public struct Size : IEquatable - { - /// - /// Represents a that has Width and Height values set to zero. - /// - public static readonly Size Empty = default(Size); - - /// - /// Initializes a new instance of the struct. - /// - /// The width of the size. - /// The height of the size. - public Size(int width, int height) - { - this.Width = width; - this.Height = height; - } - - /// - /// Gets or sets the width of this . - /// - public int Width { get; set; } - - /// - /// Gets or sets the height of this . - /// - public int Height { get; set; } - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Computes the sum of adding two sizes. - /// - /// The size on the left hand of the operand. - /// The size on the right hand of the operand. - /// - /// The - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size operator +(Size left, Size right) - { - return new Size(left.Width + right.Width, left.Height + right.Height); - } - - /// - /// Computes the difference left by subtracting one size from another. - /// - /// The size on the left hand of the operand. - /// The size on the right hand of the operand. - /// - /// The - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size operator -(Size left, Size right) - { - return new Size(left.Width - right.Width, left.Height - right.Height); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Size left, Size right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(Size left, Size right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Size [ Empty ]"; - } - - return $"Size [ Width={this.Width}, Height={this.Height} ]"; - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) - { - if (obj is Size) - { - return this.Equals((Size)obj); - } - - return false; - } - - /// - public bool Equals(Size other) - { - return this.Width == other.Width && this.Height == other.Height; - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(Size size) - { - return size.Width ^ size.Height; - } - } -} diff --git a/src/ImageSharp46/PixelAccessor.cs b/src/ImageSharp46/PixelAccessor.cs deleted file mode 100644 index 5c2ec5065..000000000 --- a/src/ImageSharp46/PixelAccessor.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Runtime.CompilerServices; - - /// - /// An optimized pixel accessor for the class. - /// - public sealed unsafe class PixelAccessor : PixelAccessor - { - /// - /// Initializes a new instance of the class. - /// - /// The image to provide pixel access for. - public PixelAccessor(ImageBase image) - : base(image) - { - } - - /// - protected override void CopyFromZYX(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - for (int x = 0; x < width; x++) - { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24)); - - source += 3; - destination += 4; - } - } - - /// - protected override void CopyFromZYXW(PixelRow row, int targetY, int width) - { - byte* source = row.PixelBase; - byte* destination = this.GetRowPointer(targetY); - - for (int x = 0; x < width; x++) - { - Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24)); - - source += 4; - destination += 4; - } - } - - /// - protected override void CopyToZYX(PixelRow row, int sourceY, int width) - { - byte* source = this.GetRowPointer(sourceY); - byte* destination = row.PixelBase; - - for (int x = 0; x < width; x++) - { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - - source += 4; - destination += 3; - } - } - - /// - protected override void CopyToZYXW(PixelRow row, int sourceY, int width) - { - byte* source = this.GetRowPointer(sourceY); - byte* destination = row.PixelBase; - - for (int x = 0; x < width; x++) - { - *destination = *(source + 2); - *(destination + 1) = *(source + 1); - *(destination + 2) = *(source + 0); - *(destination + 3) = *(source + 3); - - source += 4; - destination += 4; - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifDataType.cs b/src/ImageSharp46/Profiles/Exif/ExifDataType.cs deleted file mode 100644 index f2d012c6c..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifDataType.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Specifies exif data types. - /// - public enum ExifDataType - { - /// - /// Unknown - /// - Unknown, - - /// - /// Byte - /// - Byte, - - /// - /// Ascii - /// - Ascii, - - /// - /// Short - /// - Short, - - /// - /// Long - /// - Long, - - /// - /// Rational - /// - Rational, - - /// - /// SignedByte - /// - SignedByte, - - /// - /// Undefined - /// - Undefined, - - /// - /// SignedShort - /// - SignedShort, - - /// - /// SignedLong - /// - SignedLong, - - /// - /// SignedRational - /// - SignedRational, - - /// - /// SingleFloat - /// - SingleFloat, - - /// - /// DoubleFloat - /// - DoubleFloat - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifParts.cs b/src/ImageSharp46/Profiles/Exif/ExifParts.cs deleted file mode 100644 index 880a43453..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifParts.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - /// - /// Specifies which parts will be written when the profile is added to an image. - /// - [Flags] - public enum ExifParts - { - /// - /// None - /// - None = 0, - - /// - /// IfdTags - /// - IfdTags = 1, - - /// - /// ExifTags - /// - ExifTags = 4, - - /// - /// GPSTags - /// - GPSTags = 8, - - /// - /// All - /// - All = IfdTags | ExifTags | GPSTags - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifProfile.cs b/src/ImageSharp46/Profiles/Exif/ExifProfile.cs deleted file mode 100644 index 7694ef7c6..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifProfile.cs +++ /dev/null @@ -1,239 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.IO; - - /// - /// Represents an EXIF profile providing access to the collection of values. - /// - public sealed class ExifProfile - { - /// - /// The byte array to read the EXIF profile from. - /// - private readonly byte[] data; - - /// - /// The collection of EXIF values - /// - private Collection values; - - /// - /// The list of invalid EXIF tags - /// - private List invalidTags; - - /// - /// The thumbnail offset position in the byte stream - /// - private int thumbnailOffset; - - /// - /// The thumbnail length in the byte stream - /// - private int thumbnailLength; - - /// - /// Initializes a new instance of the class. - /// - public ExifProfile() - : this((byte[])null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The byte array to read the EXIF profile from. - public ExifProfile(byte[] data) - { - this.Parts = ExifParts.All; - this.data = data; - this.invalidTags = new List(); - } - - /// - /// Initializes a new instance of the class - /// by making a copy from another EXIF profile. - /// - /// The other EXIF profile, where the clone should be made from. - /// is null. - public ExifProfile(ExifProfile other) - { - Guard.NotNull(other, nameof(other)); - - this.Parts = other.Parts; - this.thumbnailLength = other.thumbnailLength; - this.thumbnailOffset = other.thumbnailOffset; - this.invalidTags = new List(other.invalidTags); - if (other.values != null) - { - this.values = new Collection(); - foreach (ExifValue value in other.values) - { - this.values.Add(new ExifValue(value)); - } - } - else - { - this.data = other.data; - } - } - - /// - /// Gets or sets which parts will be written when the profile is added to an image. - /// - public ExifParts Parts - { - get; - set; - } - - /// - /// Gets the tags that where found but contained an invalid value. - /// - public IEnumerable InvalidTags => this.invalidTags; - - /// - /// Gets the values of this EXIF profile. - /// - public IEnumerable Values - { - get - { - this.InitializeValues(); - return this.values; - } - } - - /// - /// Returns the thumbnail in the EXIF profile when available. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public Image CreateThumbnail() - where TColor : struct, IPackedPixel - where TPacked : struct - { - this.InitializeValues(); - - if (this.thumbnailOffset == 0 || this.thumbnailLength == 0) - { - return null; - } - - if (this.data.Length < (this.thumbnailOffset + this.thumbnailLength)) - { - return null; - } - - using (MemoryStream memStream = new MemoryStream(this.data, this.thumbnailOffset, this.thumbnailLength)) - { - return new Image(memStream); - } - } - - /// - /// Returns the value with the specified tag. - /// - /// The tag of the EXIF value. - public ExifValue GetValue(ExifTag tag) - { - foreach (ExifValue exifValue in this.Values) - { - if (exifValue.Tag == tag) - { - return exifValue; - } - } - - return null; - } - - /// - /// Removes the value with the specified tag. - /// - /// The tag of the EXIF value. - public bool RemoveValue(ExifTag tag) - { - this.InitializeValues(); - - for (int i = 0; i < this.values.Count; i++) - { - if (this.values[i].Tag == tag) - { - this.values.RemoveAt(i); - return true; - } - } - - return false; - } - - /// - /// Sets the value of the specified tag. - /// - /// The tag of the EXIF value. - /// The value. - public void SetValue(ExifTag tag, object value) - { - foreach (ExifValue exifValue in this.Values) - { - if (exifValue.Tag == tag) - { - exifValue.Value = value; - return; - } - } - - ExifValue newExifValue = ExifValue.Create(tag, value); - this.values.Add(newExifValue); - } - - /// - /// Converts this instance to a byte array. - /// - /// The - public byte[] ToByteArray() - { - if (this.values == null) - { - return this.data; - } - - if (this.values.Count == 0) - { - return null; - } - - ExifWriter writer = new ExifWriter(this.values, this.Parts); - return writer.GetData(); - } - - private void InitializeValues() - { - if (this.values != null) - { - return; - } - - if (this.data == null) - { - this.values = new Collection(); - return; - } - - ExifReader reader = new ExifReader(); - this.values = reader.Read(this.data); - this.invalidTags = new List(reader.InvalidTags); - this.thumbnailOffset = (int)reader.ThumbnailOffset; - this.thumbnailLength = (int)reader.ThumbnailLength; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifReader.cs b/src/ImageSharp46/Profiles/Exif/ExifReader.cs deleted file mode 100644 index eef6f6f3a..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifReader.cs +++ /dev/null @@ -1,515 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; - using System.Text; - - /// - /// Reads and parses EXIF data from a byte array - /// - internal sealed class ExifReader - { - private delegate TDataType ConverterMethod(byte[] data); - - private readonly Collection invalidTags = new Collection(); - private byte[] exifData; - private uint currentIndex; - private bool isLittleEndian; - private uint exifOffset; - private uint gpsOffset; - private uint startIndex; - - /// - /// Gets the thumbnail length in the byte stream - /// - public uint ThumbnailLength - { - get; - private set; - } - - /// - /// Gets the thumbnail offset position in the byte stream - /// - public uint ThumbnailOffset - { - get; - private set; - } - - /// - /// Gets the remaining length. - /// - private int RemainingLength - { - get - { - if (this.currentIndex >= this.exifData.Length) - { - return 0; - } - - return this.exifData.Length - (int)this.currentIndex; - } - } - - /// - /// Reads and returns the collection of EXIF values. - /// - /// The data. - /// - /// The . - /// - public Collection Read(byte[] data) - { - Collection result = new Collection(); - - this.exifData = data; - - if (this.GetString(4) == "Exif") - { - if (this.GetShort() != 0) - { - return result; - } - - this.startIndex = 6; - } - else - { - this.currentIndex = 0; - } - - this.isLittleEndian = this.GetString(2) == "II"; - - if (this.GetShort() != 0x002A) - { - return result; - } - - uint ifdOffset = this.GetLong(); - this.AddValues(result, ifdOffset); - - uint thumbnailOffset = this.GetLong(); - this.GetThumbnail(thumbnailOffset); - - if (this.exifOffset != 0) - { - this.AddValues(result, this.exifOffset); - } - - if (this.gpsOffset != 0) - { - this.AddValues(result, this.gpsOffset); - } - - return result; - } - - public IEnumerable InvalidTags => this.invalidTags; - - private void AddValues(Collection values, uint index) - { - this.currentIndex = this.startIndex + index; - ushort count = this.GetShort(); - - for (ushort i = 0; i < count; i++) - { - ExifValue value = this.CreateValue(); - if (value == null) - { - continue; - } - - bool duplicate = false; - foreach (ExifValue val in values) - { - if (val.Tag == value.Tag) - { - duplicate = true; - break; - } - } - - if (duplicate) - { - continue; - } - - if (value.Tag == ExifTag.SubIFDOffset) - { - if (value.DataType == ExifDataType.Long) - { - this.exifOffset = (uint)value.Value; - } - } - else if (value.Tag == ExifTag.GPSIFDOffset) - { - if (value.DataType == ExifDataType.Long) - { - this.gpsOffset = (uint)value.Value; - } - } - else - { - values.Add(value); - } - } - } - - private object ConvertValue(ExifDataType dataType, byte[] data, uint numberOfComponents) - { - if (data == null || data.Length == 0) - { - return null; - } - - switch (dataType) - { - case ExifDataType.Unknown: - return null; - case ExifDataType.Ascii: - return ToString(data); - case ExifDataType.Byte: - if (numberOfComponents == 1) - { - return ToByte(data); - } - - return data; - case ExifDataType.DoubleFloat: - if (numberOfComponents == 1) - { - return this.ToDouble(data); - } - - return ToArray(dataType, data, this.ToDouble); - case ExifDataType.Long: - if (numberOfComponents == 1) - { - return this.ToLong(data); - } - - return ToArray(dataType, data, this.ToLong); - case ExifDataType.Rational: - if (numberOfComponents == 1) - { - return this.ToRational(data); - } - - return ToArray(dataType, data, this.ToRational); - case ExifDataType.Short: - if (numberOfComponents == 1) - { - return this.ToShort(data); - } - - return ToArray(dataType, data, this.ToShort); - case ExifDataType.SignedByte: - if (numberOfComponents == 1) - { - return this.ToSignedByte(data); - } - - return ToArray(dataType, data, this.ToSignedByte); - case ExifDataType.SignedLong: - if (numberOfComponents == 1) - { - return this.ToSignedLong(data); - } - - return ToArray(dataType, data, this.ToSignedLong); - case ExifDataType.SignedRational: - if (numberOfComponents == 1) - { - return this.ToSignedRational(data); - } - - return ToArray(dataType, data, this.ToSignedRational); - case ExifDataType.SignedShort: - if (numberOfComponents == 1) - { - return this.ToSignedShort(data); - } - - return ToArray(dataType, data, this.ToSignedShort); - case ExifDataType.SingleFloat: - if (numberOfComponents == 1) - { - return this.ToSingle(data); - } - - return ToArray(dataType, data, this.ToSingle); - case ExifDataType.Undefined: - if (numberOfComponents == 1) - { - return ToByte(data); - } - - return data; - default: - throw new NotSupportedException(); - } - } - - private ExifValue CreateValue() - { - if (this.RemainingLength < 12) - { - return null; - } - - ExifTag tag = this.ToEnum(this.GetShort(), ExifTag.Unknown); - ExifDataType dataType = this.ToEnum(this.GetShort(), ExifDataType.Unknown); - object value; - - if (dataType == ExifDataType.Unknown) - { - return new ExifValue(tag, dataType, null, false); - } - - uint numberOfComponents = this.GetLong(); - - uint size = numberOfComponents * ExifValue.GetSize(dataType); - byte[] data = this.GetBytes(4); - - if (size > 4) - { - uint oldIndex = this.currentIndex; - this.currentIndex = this.ToLong(data) + this.startIndex; - if (this.RemainingLength < size) - { - this.invalidTags.Add(tag); - this.currentIndex = oldIndex; - return null; - } - - value = this.ConvertValue(dataType, this.GetBytes(size), numberOfComponents); - this.currentIndex = oldIndex; - } - else - { - value = this.ConvertValue(dataType, data, numberOfComponents); - } - - bool isArray = value != null && numberOfComponents > 1; - return new ExifValue(tag, dataType, value, isArray); - } - - private TEnum ToEnum(int value, TEnum defaultValue) - where TEnum : struct - { - TEnum enumValue = (TEnum)(object)value; - if (Enum.GetValues(typeof(TEnum)).Cast().Any(v => v.Equals(enumValue))) - { - return enumValue; - } - - return defaultValue; - } - - private byte[] GetBytes(uint length) - { - if (this.currentIndex + length > (uint)this.exifData.Length) - { - return null; - } - - byte[] data = new byte[length]; - Array.Copy(this.exifData, (int)this.currentIndex, data, 0, (int)length); - this.currentIndex += length; - - return data; - } - - private uint GetLong() - { - return this.ToLong(this.GetBytes(4)); - } - - private ushort GetShort() - { - return this.ToShort(this.GetBytes(2)); - } - - private string GetString(uint length) - { - return ToString(this.GetBytes(length)); - } - - private void GetThumbnail(uint offset) - { - Collection values = new Collection(); - this.AddValues(values, offset); - - foreach (ExifValue value in values) - { - if (value.Tag == ExifTag.JPEGInterchangeFormat && (value.DataType == ExifDataType.Long)) - { - this.ThumbnailOffset = (uint)value.Value + this.startIndex; - } - else if (value.Tag == ExifTag.JPEGInterchangeFormatLength && value.DataType == ExifDataType.Long) - { - this.ThumbnailLength = (uint)value.Value; - } - } - } - - private static TDataType[] ToArray(ExifDataType dataType, byte[] data, ConverterMethod converter) - { - int dataTypeSize = (int)ExifValue.GetSize(dataType); - int length = data.Length / dataTypeSize; - - TDataType[] result = new TDataType[length]; - byte[] buffer = new byte[dataTypeSize]; - - for (int i = 0; i < length; i++) - { - Array.Copy(data, i * dataTypeSize, buffer, 0, dataTypeSize); - - result.SetValue(converter(buffer), i); - } - - return result; - } - - private static byte ToByte(byte[] data) - { - return data[0]; - } - - private double ToDouble(byte[] data) - { - if (!this.ValidateArray(data, 8)) - { - return default(double); - } - - return BitConverter.ToDouble(data, 0); - } - - private uint ToLong(byte[] data) - { - if (!this.ValidateArray(data, 4)) - { - return default(uint); - } - - return BitConverter.ToUInt32(data, 0); - } - - private ushort ToShort(byte[] data) - { - if (!this.ValidateArray(data, 2)) - { - return default(ushort); - } - - return BitConverter.ToUInt16(data, 0); - } - - private float ToSingle(byte[] data) - { - if (!this.ValidateArray(data, 4)) - { - return default(float); - } - - return BitConverter.ToSingle(data, 0); - } - - private static string ToString(byte[] data) - { - string result = Encoding.UTF8.GetString(data, 0, data.Length); - int nullCharIndex = result.IndexOf('\0'); - if (nullCharIndex != -1) - { - result = result.Substring(0, nullCharIndex); - } - - return result; - } - - private Rational ToRational(byte[] data) - { - if (!this.ValidateArray(data, 8, 4)) - { - return default(Rational); - } - - uint numerator = BitConverter.ToUInt32(data, 0); - uint denominator = BitConverter.ToUInt32(data, 4); - - return new Rational(numerator, denominator, false); - } - - private sbyte ToSignedByte(byte[] data) - { - return unchecked((sbyte)data[0]); - } - - private int ToSignedLong(byte[] data) - { - if (!this.ValidateArray(data, 4)) - { - return default(int); - } - - return BitConverter.ToInt32(data, 0); - } - - private SignedRational ToSignedRational(byte[] data) - { - if (!this.ValidateArray(data, 8, 4)) - { - return default(SignedRational); - } - - int numerator = BitConverter.ToInt32(data, 0); - int denominator = BitConverter.ToInt32(data, 4); - - return new SignedRational(numerator, denominator, false); - } - - private short ToSignedShort(byte[] data) - { - if (!this.ValidateArray(data, 2)) - { - return default(short); - } - - return BitConverter.ToInt16(data, 0); - } - - private bool ValidateArray(byte[] data, int size) - { - return this.ValidateArray(data, size, size); - } - - private bool ValidateArray(byte[] data, int size, int stepSize) - { - if (data == null || data.Length < size) - { - return false; - } - - if (this.isLittleEndian == BitConverter.IsLittleEndian) - { - return true; - } - - for (int i = 0; i < data.Length; i += stepSize) - { - Array.Reverse(data, i, stepSize); - } - - return true; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifTag.cs b/src/ImageSharp46/Profiles/Exif/ExifTag.cs deleted file mode 100644 index 43f725f0c..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifTag.cs +++ /dev/null @@ -1,1547 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -// Descriptions from: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html - -namespace ImageSharp -{ - /// - /// All exif tags from the Exif standard 2.2 - /// - public enum ExifTag - { - /// - /// Unknown - /// - Unknown = 0xFFFF, - - /// - /// SubIFDOffset - /// - SubIFDOffset = 0x8769, - - /// - /// GPSIFDOffset - /// - GPSIFDOffset = 0x8825, - - /// - /// SubfileType - /// - [ExifTagDescription((uint)0, "Full-resolution Image")] - [ExifTagDescription((uint)1, "Reduced-resolution image")] - [ExifTagDescription((uint)2, "Single page of multi-page image")] - [ExifTagDescription((uint)3, "Single page of multi-page reduced-resolution image")] - [ExifTagDescription((uint)4, "Transparency mask")] - [ExifTagDescription((uint)5, "Transparency mask of reduced-resolution image")] - [ExifTagDescription((uint)6, "Transparency mask of multi-page image")] - [ExifTagDescription((uint)7, "Transparency mask of reduced-resolution multi-page image")] - [ExifTagDescription((uint)0x10001, "Alternate reduced-resolution image ")] - SubfileType = 0x00FE, - - /// - /// OldSubfileType - /// - [ExifTagDescription((ushort)1, "Full-resolution Image")] - [ExifTagDescription((ushort)2, "Reduced-resolution image")] - [ExifTagDescription((ushort)3, "Single page of multi-page image")] - OldSubfileType = 0x00FF, - - /// - /// ImageWidth - /// - ImageWidth = 0x0100, - - /// - /// ImageLength - /// - ImageLength = 0x0101, - - /// - /// BitsPerSample - /// - BitsPerSample = 0x0102, - - /// - /// Compression - /// - [ExifTagDescription((ushort)1, "Uncompressed")] - [ExifTagDescription((ushort)2, "CCITT 1D")] - [ExifTagDescription((ushort)3, "T4/Group 3 Fax")] - [ExifTagDescription((ushort)4, "T6/Group 4 Fax")] - [ExifTagDescription((ushort)5, "LZW")] - [ExifTagDescription((ushort)6, "JPEG (old-style)")] - [ExifTagDescription((ushort)7, "JPEG")] - [ExifTagDescription((ushort)8, "Adobe Deflate")] - [ExifTagDescription((ushort)9, "JBIG B&W")] - [ExifTagDescription((ushort)10, "JBIG Color")] - [ExifTagDescription((ushort)99, "JPEG")] - [ExifTagDescription((ushort)262, "Kodak 262")] - [ExifTagDescription((ushort)32766, "Next")] - [ExifTagDescription((ushort)32767, "Sony ARW Compressed")] - [ExifTagDescription((ushort)32769, "Packed RAW")] - [ExifTagDescription((ushort)32770, "Samsung SRW Compressed")] - [ExifTagDescription((ushort)32771, "CCIRLEW")] - [ExifTagDescription((ushort)32772, "Samsung SRW Compressed 2")] - [ExifTagDescription((ushort)32773, "PackBits")] - [ExifTagDescription((ushort)32809, "Thunderscan")] - [ExifTagDescription((ushort)32867, "Kodak KDC Compressed")] - [ExifTagDescription((ushort)32895, "IT8CTPAD")] - [ExifTagDescription((ushort)32896, "IT8LW")] - [ExifTagDescription((ushort)32897, "IT8MP")] - [ExifTagDescription((ushort)32898, "IT8BL")] - [ExifTagDescription((ushort)32908, "PixarFilm")] - [ExifTagDescription((ushort)32909, "PixarLog")] - [ExifTagDescription((ushort)32946, "Deflate")] - [ExifTagDescription((ushort)32947, "DCS")] - [ExifTagDescription((ushort)34661, "JBIG")] - [ExifTagDescription((ushort)34676, "SGILog")] - [ExifTagDescription((ushort)34677, "SGILog24")] - [ExifTagDescription((ushort)34712, "JPEG 2000")] - [ExifTagDescription((ushort)34713, "Nikon NEF Compressed")] - [ExifTagDescription((ushort)34715, "JBIG2 TIFF FX")] - [ExifTagDescription((ushort)34718, "Microsoft Document Imaging (MDI) Binary Level Codec")] - [ExifTagDescription((ushort)34719, "Microsoft Document Imaging (MDI) Progressive Transform Codec")] - [ExifTagDescription((ushort)34720, "Microsoft Document Imaging (MDI) Vector")] - [ExifTagDescription((ushort)34892, "Lossy JPEG")] - [ExifTagDescription((ushort)65000, "Kodak DCR Compressed")] - [ExifTagDescription((ushort)65535, "Pentax PEF Compressed")] - Compression = 0x0103, - - /// - /// PhotometricInterpretation - /// - [ExifTagDescription((ushort)0, "WhiteIsZero")] - [ExifTagDescription((ushort)1, "BlackIsZero")] - [ExifTagDescription((ushort)2, "RGB")] - [ExifTagDescription((ushort)3, "RGB Palette")] - [ExifTagDescription((ushort)4, "Transparency Mask")] - [ExifTagDescription((ushort)5, "CMYK")] - [ExifTagDescription((ushort)6, "YCbCr")] - [ExifTagDescription((ushort)8, "CIELab")] - [ExifTagDescription((ushort)9, "ICCLab")] - [ExifTagDescription((ushort)10, "TULab")] - [ExifTagDescription((ushort)32803, "Color Filter Array")] - [ExifTagDescription((ushort)32844, "Pixar LogL")] - [ExifTagDescription((ushort)32845, "Pixar LogLuv")] - [ExifTagDescription((ushort)34892, "Linear Raw")] - PhotometricInterpretation = 0x0106, - - /// - /// Thresholding - /// - [ExifTagDescription((ushort)1, "No dithering or halftoning")] - [ExifTagDescription((ushort)2, "Ordered dither or halftone")] - [ExifTagDescription((ushort)3, "Randomized dither")] - Thresholding = 0x0107, - - /// - /// CellWidth - /// - CellWidth = 0x0108, - - /// - /// CellLength - /// - CellLength = 0x0109, - - /// - /// FillOrder - /// - [ExifTagDescription((ushort)1, "Normal")] - [ExifTagDescription((ushort)2, "Reversed")] - FillOrder = 0x010A, - - /// - /// DocumentName - /// - DocumentName = 0x010D, - - /// - /// ImageDescription - /// - ImageDescription = 0x010E, - - /// - /// Make - /// - Make = 0x010F, - - /// - /// Model - /// - Model = 0x0110, - - /// - /// StripOffsets - /// - StripOffsets = 0x0111, - - /// - /// Orientation - /// - [ExifTagDescription((ushort)1, "Horizontal (normal)")] - [ExifTagDescription((ushort)2, "Mirror horizontal")] - [ExifTagDescription((ushort)3, "Rotate 180")] - [ExifTagDescription((ushort)4, "Mirror vertical")] - [ExifTagDescription((ushort)5, "Mirror horizontal and rotate 270 CW")] - [ExifTagDescription((ushort)6, "Rotate 90 CW")] - [ExifTagDescription((ushort)7, "Mirror horizontal and rotate 90 CW")] - [ExifTagDescription((ushort)8, "Rotate 270 CW")] - Orientation = 0x0112, - - /// - /// SamplesPerPixel - /// - SamplesPerPixel = 0x0115, - - /// - /// RowsPerStrip - /// - RowsPerStrip = 0x0116, - - /// - /// StripByteCounts - /// - StripByteCounts = 0x0117, - - /// - /// MinSampleValue - /// - MinSampleValue = 0x0118, - - /// - /// MaxSampleValue - /// - MaxSampleValue = 0x0119, - - /// - /// XResolution - /// - XResolution = 0x011A, - - /// - /// YResolution - /// - YResolution = 0x011B, - - /// - /// PlanarConfiguration - /// - [ExifTagDescription((ushort)1, "Chunky")] - [ExifTagDescription((ushort)2, "Planar")] - PlanarConfiguration = 0x011C, - - /// - /// PageName - /// - PageName = 0x011D, - - /// - /// XPosition - /// - XPosition = 0x011E, - - /// - /// YPosition - /// - YPosition = 0x011F, - - /// - /// FreeOffsets - /// - FreeOffsets = 0x0120, - - /// - /// FreeByteCounts - /// - FreeByteCounts = 0x0121, - - /// - /// GrayResponseUnit - /// - [ExifTagDescription((ushort)1, "0.1")] - [ExifTagDescription((ushort)2, "0.001")] - [ExifTagDescription((ushort)3, "0.0001")] - [ExifTagDescription((ushort)4, "1e-05")] - [ExifTagDescription((ushort)5, "1e-06")] - GrayResponseUnit = 0x0122, - - /// - /// GrayResponseCurve - /// - GrayResponseCurve = 0x0123, - - /// - /// T4Options - /// - [ExifTagDescription((uint)0, "2-Dimensional encoding")] - [ExifTagDescription((uint)1, "Uncompressed")] - [ExifTagDescription((uint)2, "Fill bits added")] - T4Options = 0x0124, - - /// - /// T6Options - /// - [ExifTagDescription((uint)1, "Uncompressed")] - T6Options = 0x0125, - - /// - /// ResolutionUnit - /// - [ExifTagDescription((ushort)1, "None")] - [ExifTagDescription((ushort)2, "Inches")] - [ExifTagDescription((ushort)3, "Centimeter")] - ResolutionUnit = 0x0128, - - /// - /// PageNumber - /// - PageNumber = 0x0129, - - /// - /// ColorResponseUnit - /// - ColorResponseUnit = 0x012C, - - /// - /// TransferFunction - /// - TransferFunction = 0x012D, - - /// - /// Software - /// - Software = 0x0131, - - /// - /// DateTime - /// - DateTime = 0x0132, - - /// - /// Artist - /// - Artist = 0x013B, - - /// - /// HostComputer - /// - HostComputer = 0x013C, - - /// - /// Predictor - /// - Predictor = 0x013D, - - /// - /// WhitePoint - /// - WhitePoint = 0x013E, - - /// - /// PrimaryChromaticities - /// - PrimaryChromaticities = 0x013F, - - /// - /// ColorMap - /// - ColorMap = 0x0140, - - /// - /// HalftoneHints - /// - HalftoneHints = 0x0141, - - /// - /// TileWidth - /// - TileWidth = 0x0142, - - /// - /// TileLength - /// - TileLength = 0x0143, - - /// - /// TileOffsets - /// - TileOffsets = 0x0144, - - /// - /// TileByteCounts - /// - TileByteCounts = 0x0145, - - /// - /// BadFaxLines - /// - BadFaxLines = 0x0146, - - /// - /// CleanFaxData - /// - [ExifTagDescription((uint)0, "Clean")] - [ExifTagDescription((uint)1, "Regenerated")] - [ExifTagDescription((uint)2, "Unclean")] - CleanFaxData = 0x0147, - - /// - /// ConsecutiveBadFaxLines - /// - ConsecutiveBadFaxLines = 0x0148, - - /// - /// InkSet - /// - [ExifTagDescription((ushort)1, "CMYK")] - [ExifTagDescription((ushort)2, "Not CMYK")] - InkSet = 0x014C, - - /// - /// InkNames - /// - InkNames = 0x014D, - - /// - /// NumberOfInks - /// - NumberOfInks = 0x014E, - - /// - /// DotRange - /// - DotRange = 0x0150, - - /// - /// TargetPrinter - /// - TargetPrinter = 0x0151, - - /// - /// ExtraSamples - /// - [ExifTagDescription((ushort)0, "Unspecified")] - [ExifTagDescription((ushort)1, "Associated Alpha")] - [ExifTagDescription((ushort)2, "Unassociated Alpha")] - ExtraSamples = 0x0152, - - /// - /// SampleFormat - /// - [ExifTagDescription((ushort)1, "Unsigned")] - [ExifTagDescription((ushort)2, "Signed")] - [ExifTagDescription((ushort)3, "Float")] - [ExifTagDescription((ushort)4, "Undefined")] - [ExifTagDescription((ushort)5, "Complex int")] - [ExifTagDescription((ushort)6, "Complex float")] - SampleFormat = 0x0153, - - /// - /// SMinSampleValue - /// - SMinSampleValue = 0x0154, - - /// - /// SMaxSampleValue - /// - SMaxSampleValue = 0x0155, - - /// - /// TransferRange - /// - TransferRange = 0x0156, - - /// - /// ClipPath - /// - ClipPath = 0x0157, - - /// - /// XClipPathUnits - /// - XClipPathUnits = 0x0158, - - /// - /// YClipPathUnits - /// - YClipPathUnits = 0x0159, - - /// - /// Indexed - /// - [ExifTagDescription((ushort)0, "Not indexed")] - [ExifTagDescription((ushort)1, "Indexed")] - Indexed = 0x015A, - - /// - /// JPEGTables - /// - JPEGTables = 0x015B, - - /// - /// OPIProxy - /// - [ExifTagDescription((ushort)0, "Higher resolution image does not exist")] - [ExifTagDescription((ushort)1, "Higher resolution image exists")] - OPIProxy = 0x015F, - - /// - /// ProfileType - /// - [ExifTagDescription((uint)0, "Unspecified")] - [ExifTagDescription((uint)1, "Group 3 FAX")] - ProfileType = 0x0191, - - /// - /// FaxProfile - /// - [ExifTagDescription((byte)0, "Unknown")] - [ExifTagDescription((byte)1, "Minimal B&W lossless, S")] - [ExifTagDescription((byte)2, "Extended B&W lossless, F")] - [ExifTagDescription((byte)3, "Lossless JBIG B&W, J")] - [ExifTagDescription((byte)4, "Lossy color and grayscale, C")] - [ExifTagDescription((byte)5, "Lossless color and grayscale, L")] - [ExifTagDescription((byte)6, "Mixed raster content, M")] - [ExifTagDescription((byte)7, "Profile T")] - [ExifTagDescription((byte)255, "Multi Profiles")] - FaxProfile = 0x0192, - - /// - /// CodingMethods - /// - [ExifTagDescription((ulong)0, "Unspecified compression")] - [ExifTagDescription((ulong)1, "Modified Huffman")] - [ExifTagDescription((ulong)2, "Modified Read")] - [ExifTagDescription((ulong)4, "Modified MR")] - [ExifTagDescription((ulong)8, "JBIG")] - [ExifTagDescription((ulong)16, "Baseline JPEG")] - [ExifTagDescription((ulong)32, "JBIG color")] - CodingMethods = 0x0193, - - /// - /// VersionYear - /// - VersionYear = 0x0194, - - /// - /// ModeNumber - /// - ModeNumber = 0x0195, - - /// - /// Decode - /// - Decode = 0x01B1, - - /// - /// DefaultImageColor - /// - DefaultImageColor = 0x01B2, - - /// - /// T82ptions - /// - T82ptions = 0x01B3, - - /// - /// JPEGProc - /// - [ExifTagDescription((ushort)1, "Baseline")] - [ExifTagDescription((ushort)14, "Lossless")] - JPEGProc = 0x0200, - - /// - /// JPEGInterchangeFormat - /// - JPEGInterchangeFormat = 0x0201, - - /// - /// JPEGInterchangeFormatLength - /// - JPEGInterchangeFormatLength = 0x0202, - - /// - /// JPEGRestartInterval - /// - JPEGRestartInterval = 0x0203, - - /// - /// JPEGLosslessPredictors - /// - JPEGLosslessPredictors = 0x0205, - - /// - /// JPEGPointTransforms - /// - JPEGPointTransforms = 0x0206, - - /// - /// JPEGQTables - /// - JPEGQTables = 0x0207, - - /// - /// JPEGDCTables - /// - JPEGDCTables = 0x0208, - - /// - /// JPEGACTables - /// - JPEGACTables = 0x0209, - - /// - /// YCbCrCoefficients - /// - YCbCrCoefficients = 0x0211, - - /// - /// YCbCrSubsampling - /// - YCbCrSubsampling = 0x0212, - - /// - /// YCbCrPositioning - /// - [ExifTagDescription((ushort)1, "Centered")] - [ExifTagDescription((ushort)2, "Co-sited")] - YCbCrPositioning = 0x0213, - - /// - /// ReferenceBlackWhite - /// - ReferenceBlackWhite = 0x0214, - - /// - /// StripRowCounts - /// - StripRowCounts = 0x022F, - - /// - /// XMP - /// - XMP = 0x02BC, - - /// - /// Rating - /// - Rating = 0x4746, - - /// - /// RatingPercent - /// - RatingPercent = 0x4749, - - /// - /// ImageID - /// - ImageID = 0x800D, - - /// - /// CFARepeatPatternDim - /// - CFARepeatPatternDim = 0x828D, - - /// - /// CFAPattern2 - /// - CFAPattern2 = 0x828E, - - /// - /// BatteryLevel - /// - BatteryLevel = 0x828F, - - /// - /// Copyright - /// - Copyright = 0x8298, - - /// - /// ExposureTime - /// - ExposureTime = 0x829A, - - /// - /// FNumber - /// - FNumber = 0x829D, - - /// - /// MDFileTag - /// - MDFileTag = 0x82A5, - - /// - /// MDScalePixel - /// - MDScalePixel = 0x82A6, - - /// - /// MDLabName - /// - MDLabName = 0x82A8, - - /// - /// MDSampleInfo - /// - MDSampleInfo = 0x82A9, - - /// - /// MDPrepDate - /// - MDPrepDate = 0x82AA, - - /// - /// MDPrepTime - /// - MDPrepTime = 0x82AB, - - /// - /// MDFileUnits - /// - MDFileUnits = 0x82AC, - - /// - /// PixelScale - /// - PixelScale = 0x830E, - - /// - /// IntergraphPacketData - /// - IntergraphPacketData = 0x847E, - - /// - /// IntergraphRegisters - /// - IntergraphRegisters = 0x847F, - - /// - /// IntergraphMatrix - /// - IntergraphMatrix = 0x8480, - - /// - /// ModelTiePoint - /// - ModelTiePoint = 0x8482, - - /// - /// SEMInfo - /// - SEMInfo = 0x8546, - - /// - /// ModelTransform - /// - ModelTransform = 0x85D8, - - /// - /// ImageLayer - /// - ImageLayer = 0x87AC, - - /// - /// ExposureProgram - /// - [ExifTagDescription((ushort)0, "Not Defined")] - [ExifTagDescription((ushort)1, "Manual")] - [ExifTagDescription((ushort)2, "Program AE")] - [ExifTagDescription((ushort)3, "Aperture-priority AE")] - [ExifTagDescription((ushort)4, "Shutter speed priority AE")] - [ExifTagDescription((ushort)5, "Creative (Slow speed)")] - [ExifTagDescription((ushort)6, "Action (High speed)")] - [ExifTagDescription((ushort)7, "Portrait")] - [ExifTagDescription((ushort)8, "Landscape")] - [ExifTagDescription((ushort)9, "Bulb")] - ExposureProgram = 0x8822, - - /// - /// SpectralSensitivity - /// - SpectralSensitivity = 0x8824, - - /// - /// ISOSpeedRatings - /// - ISOSpeedRatings = 0x8827, - - /// - /// OECF - /// - OECF = 0x8828, - - /// - /// Interlace - /// - Interlace = 0x8829, - - /// - /// TimeZoneOffset - /// - TimeZoneOffset = 0x882A, - - /// - /// SelfTimerMode - /// - SelfTimerMode = 0x882B, - - /// - /// SensitivityType - /// - [ExifTagDescription((ushort)0, "Unknown")] - [ExifTagDescription((ushort)1, "Standard Output Sensitivity")] - [ExifTagDescription((ushort)2, "Recommended Exposure Index")] - [ExifTagDescription((ushort)3, "ISO Speed")] - [ExifTagDescription((ushort)4, "Standard Output Sensitivity and Recommended Exposure Index")] - [ExifTagDescription((ushort)5, "Standard Output Sensitivity and ISO Speed")] - [ExifTagDescription((ushort)6, "Recommended Exposure Index and ISO Speed")] - [ExifTagDescription((ushort)7, "Standard Output Sensitivity, Recommended Exposure Index and ISO Speed")] - SensitivityType = 0x8830, - - /// - /// StandardOutputSensitivity - /// - StandardOutputSensitivity = 0x8831, - - /// - /// RecommendedExposureIndex - /// - RecommendedExposureIndex = 0x8832, - - /// - /// ISOSpeed - /// - ISOSpeed = 0x8833, - - /// - /// ISOSpeedLatitudeyyy - /// - ISOSpeedLatitudeyyy = 0x8834, - - /// - /// ISOSpeedLatitudezzz - /// - ISOSpeedLatitudezzz = 0x8835, - - /// - /// FaxRecvParams - /// - FaxRecvParams = 0x885C, - - /// - /// FaxSubaddress - /// - FaxSubaddress = 0x885D, - - /// - /// FaxRecvTime - /// - FaxRecvTime = 0x885E, - - /// - /// ExifVersion - /// - ExifVersion = 0x9000, - - /// - /// DateTimeOriginal - /// - DateTimeOriginal = 0x9003, - - /// - /// DateTimeDigitized - /// - DateTimeDigitized = 0x9004, - - /// - /// OffsetTime - /// - OffsetTime = 0x9010, - - /// - /// OffsetTimeOriginal - /// - OffsetTimeOriginal = 0x9011, - - /// - /// OffsetTimeDigitized - /// - OffsetTimeDigitized = 0x9012, - - /// - /// ComponentsConfiguration - /// - ComponentsConfiguration = 0x9101, - - /// - /// CompressedBitsPerPixel - /// - CompressedBitsPerPixel = 0x9102, - - /// - /// ShutterSpeedValue - /// - ShutterSpeedValue = 0x9201, - - /// - /// ApertureValue - /// - ApertureValue = 0x9202, - - /// - /// BrightnessValue - /// - BrightnessValue = 0x9203, - - /// - /// ExposureBiasValue - /// - ExposureBiasValue = 0x9204, - - /// - /// MaxApertureValue - /// - MaxApertureValue = 0x9205, - - /// - /// SubjectDistance - /// - SubjectDistance = 0x9206, - - /// - /// MeteringMode - /// - [ExifTagDescription((ushort)0, "Unknown")] - [ExifTagDescription((ushort)1, "Average")] - [ExifTagDescription((ushort)2, "Center-weighted average")] - [ExifTagDescription((ushort)3, "Spot")] - [ExifTagDescription((ushort)4, "Multi-spot")] - [ExifTagDescription((ushort)5, "Multi-segment")] - [ExifTagDescription((ushort)6, "Partial")] - [ExifTagDescription((ushort)255, "Other")] - MeteringMode = 0x9207, - - /// - /// LightSource - /// - [ExifTagDescription((ushort)0, "Unknown")] - [ExifTagDescription((ushort)1, "Daylight")] - [ExifTagDescription((ushort)2, "Fluorescent")] - [ExifTagDescription((ushort)3, "Tungsten (Incandescent)")] - [ExifTagDescription((ushort)4, "Flash")] - [ExifTagDescription((ushort)9, "Fine Weather")] - [ExifTagDescription((ushort)10, "Cloudy")] - [ExifTagDescription((ushort)11, "Shade")] - [ExifTagDescription((ushort)12, "Daylight Fluorescent")] - [ExifTagDescription((ushort)13, "Day White Fluorescent")] - [ExifTagDescription((ushort)14, "Cool White Fluorescent")] - [ExifTagDescription((ushort)15, "White Fluorescent")] - [ExifTagDescription((ushort)16, "Warm White Fluorescent")] - [ExifTagDescription((ushort)17, "Standard Light A")] - [ExifTagDescription((ushort)18, "Standard Light B")] - [ExifTagDescription((ushort)19, "Standard Light C")] - [ExifTagDescription((ushort)20, "D55")] - [ExifTagDescription((ushort)21, "D65")] - [ExifTagDescription((ushort)22, "D75")] - [ExifTagDescription((ushort)23, "D50")] - [ExifTagDescription((ushort)24, "ISO Studio Tungsten")] - [ExifTagDescription((ushort)255, "Other")] - LightSource = 0x9208, - - /// - /// Flash - /// - [ExifTagDescription((ushort)0, "No Flash")] - [ExifTagDescription((ushort)1, "Fired")] - [ExifTagDescription((ushort)5, "Fired, Return not detected")] - [ExifTagDescription((ushort)7, "Fired, Return detected")] - [ExifTagDescription((ushort)8, "On, Did not fire")] - [ExifTagDescription((ushort)9, "On, Fired")] - [ExifTagDescription((ushort)13, "On, Return not detected")] - [ExifTagDescription((ushort)15, "On, Return detected")] - [ExifTagDescription((ushort)16, "Off, Did not fire")] - [ExifTagDescription((ushort)20, "Off, Did not fire, Return not detected")] - [ExifTagDescription((ushort)24, "Auto, Did not fire")] - [ExifTagDescription((ushort)25, "Auto, Fired")] - [ExifTagDescription((ushort)29, "Auto, Fired, Return not detected")] - [ExifTagDescription((ushort)31, "Auto, Fired, Return detected")] - [ExifTagDescription((ushort)32, "No flash function")] - [ExifTagDescription((ushort)48, "Off, No flash function")] - [ExifTagDescription((ushort)65, "Fired, Red-eye reduction")] - [ExifTagDescription((ushort)69, "Fired, Red-eye reduction, Return not detected")] - [ExifTagDescription((ushort)71, "Fired, Red-eye reduction, Return detected")] - [ExifTagDescription((ushort)73, "On, Red-eye reduction")] - [ExifTagDescription((ushort)77, "On, Red-eye reduction, Return not detected")] - [ExifTagDescription((ushort)69, "On, Red-eye reduction, Return detected")] - [ExifTagDescription((ushort)80, "Off, Red-eye reduction")] - [ExifTagDescription((ushort)88, "Auto, Did not fire, Red-eye reduction")] - [ExifTagDescription((ushort)89, "Auto, Fired, Red-eye reduction")] - [ExifTagDescription((ushort)93, "Auto, Fired, Red-eye reduction, Return not detected")] - [ExifTagDescription((ushort)95, "Auto, Fired, Red-eye reduction, Return detected")] - Flash = 0x9209, - - /// - /// FocalLength - /// - FocalLength = 0x920A, - - /// - /// FlashEnergy2 - /// - FlashEnergy2 = 0x920B, - - /// - /// SpatialFrequencyResponse2 - /// - SpatialFrequencyResponse2 = 0x920C, - - /// - /// Noise - /// - Noise = 0x920D, - - /// - /// FocalPlaneXResolution2 - /// - FocalPlaneXResolution2 = 0x920E, - - /// - /// FocalPlaneYResolution2 - /// - FocalPlaneYResolution2 = 0x920F, - - /// - /// FocalPlaneResolutionUnit2 - /// - [ExifTagDescription((ushort)1, "None")] - [ExifTagDescription((ushort)2, "Inches")] - [ExifTagDescription((ushort)3, "Centimeter")] - [ExifTagDescription((ushort)4, "Millimeter")] - [ExifTagDescription((ushort)5, "Micrometer")] - FocalPlaneResolutionUnit2 = 0x9210, - - /// - /// ImageNumber - /// - ImageNumber = 0x9211, - - /// - /// SecurityClassification - /// - [ExifTagDescription("C", "Confidential")] - [ExifTagDescription("R", "Restricted")] - [ExifTagDescription("S", "Secret")] - [ExifTagDescription("T", "Top Secret")] - [ExifTagDescription("U", "Unclassified")] - SecurityClassification = 0x9212, - - /// - /// ImageHistory - /// - ImageHistory = 0x9213, - - /// - /// SubjectArea - /// - SubjectArea = 0x9214, - - /// - /// ExposureIndex2 - /// - ExposureIndex2 = 0x9215, - - /// - /// TIFFEPStandardID - /// - TIFFEPStandardID = 0x9216, - - /// - /// SensingMethod - /// - [ExifTagDescription((ushort)1, "Not defined")] - [ExifTagDescription((ushort)2, "One-chip color area")] - [ExifTagDescription((ushort)3, "Two-chip color area")] - [ExifTagDescription((ushort)4, "Three-chip color area")] - [ExifTagDescription((ushort)5, "Color sequential area")] - [ExifTagDescription((ushort)7, "Trilinear")] - [ExifTagDescription((ushort)8, "Color sequential linear")] - SensingMethod2 = 0x9217, - - /// - /// MakerNote - /// - MakerNote = 0x927C, - - /// - /// UserComment - /// - UserComment = 0x9286, - - /// - /// SubsecTime - /// - SubsecTime = 0x9290, - - /// - /// SubsecTimeOriginal - /// - SubsecTimeOriginal = 0x9291, - - /// - /// SubsecTimeDigitized - /// - SubsecTimeDigitized = 0x9292, - - /// - /// ImageSourceData - /// - ImageSourceData = 0x935C, - - /// - /// AmbientTemperature - /// - AmbientTemperature = 0x9400, - - /// - /// Humidity - /// - Humidity = 0x9401, - - /// - /// Pressure - /// - Pressure = 0x9402, - - /// - /// WaterDepth - /// - WaterDepth = 0x9403, - - /// - /// Acceleration - /// - Acceleration = 0x9404, - - /// - /// CameraElevationAngle - /// - CameraElevationAngle = 0x9405, - - /// - /// XPTitle - /// - XPTitle = 0x9C9B, - - /// - /// XPComment - /// - XPComment = 0x9C9C, - - /// - /// XPAuthor - /// - XPAuthor = 0x9C9D, - - /// - /// XPKeywords - /// - XPKeywords = 0x9C9E, - - /// - /// XPSubject - /// - XPSubject = 0x9C9F, - - /// - /// FlashpixVersion - /// - FlashpixVersion = 0xA000, - - /// - /// ColorSpace - /// - [ExifTagDescription((ushort)1, "sRGB")] - [ExifTagDescription((ushort)2, "Adobe RGB")] - [ExifTagDescription((ushort)4093, "Wide Gamut RGB")] - [ExifTagDescription((ushort)65534, "ICC Profile")] - [ExifTagDescription((ushort)65535, "Uncalibrated")] - ColorSpace = 0xA001, - - /// - /// PixelXDimension - /// - PixelXDimension = 0xA002, - - /// - /// PixelYDimension - /// - PixelYDimension = 0xA003, - - /// - /// RelatedSoundFile - /// - RelatedSoundFile = 0xA004, - - /// - /// FlashEnergy - /// - FlashEnergy = 0xA20B, - - /// - /// SpatialFrequencyResponse - /// - SpatialFrequencyResponse = 0xA20C, - - /// - /// FocalPlaneXResolution - /// - FocalPlaneXResolution = 0xA20E, - - /// - /// FocalPlaneYResolution - /// - FocalPlaneYResolution = 0xA20F, - - /// - /// FocalPlaneResolutionUnit - /// - [ExifTagDescription((ushort)1, "None")] - [ExifTagDescription((ushort)2, "Inches")] - [ExifTagDescription((ushort)3, "Centimeter")] - [ExifTagDescription((ushort)4, "Millimeter")] - [ExifTagDescription((ushort)5, "Micrometer")] - FocalPlaneResolutionUnit = 0xA210, - - /// - /// SubjectLocation - /// - SubjectLocation = 0xA214, - - /// - /// ExposureIndex - /// - ExposureIndex = 0xA215, - - /// - /// SensingMethod - /// - [ExifTagDescription((ushort)1, "Not defined")] - [ExifTagDescription((ushort)2, "One-chip color area")] - [ExifTagDescription((ushort)3, "Two-chip color area")] - [ExifTagDescription((ushort)4, "Three-chip color area")] - [ExifTagDescription((ushort)5, "Color sequential area")] - [ExifTagDescription((ushort)7, "Trilinear")] - [ExifTagDescription((ushort)8, "Color sequential linear")] - SensingMethod = 0xA217, - - /// - /// FileSource - /// - FileSource = 0xA300, - - /// - /// SceneType - /// - SceneType = 0xA301, - - /// - /// CFAPattern - /// - CFAPattern = 0xA302, - - /// - /// CustomRendered - /// - [ExifTagDescription((ushort)1, "Normal")] - [ExifTagDescription((ushort)2, "Custom")] - CustomRendered = 0xA401, - - /// - /// ExposureMode - /// - [ExifTagDescription((ushort)0, "Auto")] - [ExifTagDescription((ushort)1, "Manual")] - [ExifTagDescription((ushort)2, "Auto bracket")] - ExposureMode = 0xA402, - - /// - /// WhiteBalance - /// - [ExifTagDescription((ushort)0, "Auto")] - [ExifTagDescription((ushort)1, "Manual")] - WhiteBalance = 0xA403, - - /// - /// DigitalZoomRatio - /// - DigitalZoomRatio = 0xA404, - - /// - /// FocalLengthIn35mmFilm - /// - FocalLengthIn35mmFilm = 0xA405, - - /// - /// SceneCaptureType - /// - [ExifTagDescription((ushort)0, "Standard")] - [ExifTagDescription((ushort)1, "Landscape")] - [ExifTagDescription((ushort)2, "Portrait")] - [ExifTagDescription((ushort)3, "Night")] - SceneCaptureType = 0xA406, - - /// - /// GainControl - /// - [ExifTagDescription((ushort)0, "None")] - [ExifTagDescription((ushort)1, "Low gain up")] - [ExifTagDescription((ushort)2, "High gain up")] - [ExifTagDescription((ushort)3, "Low gain down")] - [ExifTagDescription((ushort)4, "High gain down")] - GainControl = 0xA407, - - /// - /// Contrast - /// - [ExifTagDescription((ushort)0, "Normal")] - [ExifTagDescription((ushort)1, "Low")] - [ExifTagDescription((ushort)2, "High")] - Contrast = 0xA408, - - /// - /// Saturation - /// - [ExifTagDescription((ushort)0, "Normal")] - [ExifTagDescription((ushort)1, "Low")] - [ExifTagDescription((ushort)2, "High")] - Saturation = 0xA409, - - /// - /// Sharpness - /// - [ExifTagDescription((ushort)0, "Normal")] - [ExifTagDescription((ushort)1, "Soft")] - [ExifTagDescription((ushort)2, "Hard")] - Sharpness = 0xA40A, - - /// - /// DeviceSettingDescription - /// - DeviceSettingDescription = 0xA40B, - - /// - /// SubjectDistanceRange - /// - [ExifTagDescription((ushort)0, "Unknown")] - [ExifTagDescription((ushort)1, "Macro")] - [ExifTagDescription((ushort)2, "Close")] - [ExifTagDescription((ushort)3, "Distant")] - SubjectDistanceRange = 0xA40C, - - /// - /// ImageUniqueID - /// - ImageUniqueID = 0xA420, - - /// - /// OwnerName - /// - OwnerName = 0xA430, - - /// - /// SerialNumber - /// - SerialNumber = 0xA431, - - /// - /// LensInfo - /// - LensInfo = 0xA432, - - /// - /// LensMake - /// - LensMake = 0xA433, - - /// - /// LensModel - /// - LensModel = 0xA434, - - /// - /// LensSerialNumber - /// - LensSerialNumber = 0xA435, - - /// - /// GDALMetadata - /// - GDALMetadata = 0xA480, - - /// - /// GDALNoData - /// - GDALNoData = 0xA481, - - /// - /// GPSVersionID - /// - GPSVersionID = 0x0000, - - /// - /// GPSLatitudeRef - /// - GPSLatitudeRef = 0x0001, - - /// - /// GPSLatitude - /// - GPSLatitude = 0x0002, - - /// - /// GPSLongitudeRef - /// - GPSLongitudeRef = 0x0003, - - /// - /// GPSLongitude - /// - GPSLongitude = 0x0004, - - /// - /// GPSAltitudeRef - /// - GPSAltitudeRef = 0x0005, - - /// - /// GPSAltitude - /// - GPSAltitude = 0x0006, - - /// - /// GPSTimestamp - /// - GPSTimestamp = 0x0007, - - /// - /// GPSSatellites - /// - GPSSatellites = 0x0008, - - /// - /// GPSStatus - /// - GPSStatus = 0x0009, - - /// - /// GPSMeasureMode - /// - GPSMeasureMode = 0x000A, - - /// - /// GPSDOP - /// - GPSDOP = 0x000B, - - /// - /// GPSSpeedRef - /// - GPSSpeedRef = 0x000C, - - /// - /// GPSSpeed - /// - GPSSpeed = 0x000D, - - /// - /// GPSTrackRef - /// - GPSTrackRef = 0x000E, - - /// - /// GPSTrack - /// - GPSTrack = 0x000F, - - /// - /// GPSImgDirectionRef - /// - GPSImgDirectionRef = 0x0010, - - /// - /// GPSImgDirection - /// - GPSImgDirection = 0x0011, - - /// - /// GPSMapDatum - /// - GPSMapDatum = 0x0012, - - /// - /// GPSDestLatitudeRef - /// - GPSDestLatitudeRef = 0x0013, - - /// - /// GPSDestLatitude - /// - GPSDestLatitude = 0x0014, - - /// - /// GPSDestLongitudeRef - /// - GPSDestLongitudeRef = 0x0015, - - /// - /// GPSDestLongitude - /// - GPSDestLongitude = 0x0016, - - /// - /// GPSDestBearingRef - /// - GPSDestBearingRef = 0x0017, - - /// - /// GPSDestBearing - /// - GPSDestBearing = 0x0018, - - /// - /// GPSDestDistanceRef - /// - GPSDestDistanceRef = 0x0019, - - /// - /// GPSDestDistance - /// - GPSDestDistance = 0x001A, - - /// - /// GPSProcessingMethod - /// - GPSProcessingMethod = 0x001B, - - /// - /// GPSAreaInformation - /// - GPSAreaInformation = 0x001C, - - /// - /// GPSDateStamp - /// - GPSDateStamp = 0x001D, - - /// - /// GPSDifferential - /// - GPSDifferential = 0x001E - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifTagDescriptionAttribute.cs b/src/ImageSharp46/Profiles/Exif/ExifTagDescriptionAttribute.cs deleted file mode 100644 index ca19a9776..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifTagDescriptionAttribute.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Reflection; - - /// - /// Class that provides a description for an ExifTag value. - /// - [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] - internal sealed class ExifTagDescriptionAttribute : Attribute - { - private object value; - private string description; - - /// - /// Initializes a new instance of the class. - /// - /// The value of the exif tag. - /// The description for the value of the exif tag. - public ExifTagDescriptionAttribute(object value, string description) - { - this.value = value; - this.description = description; - } - - public static string GetDescription(ExifTag tag, object value) - { - FieldInfo field = tag.GetType().GetTypeInfo().GetDeclaredField(tag.ToString()); - if (field == null) - { - return null; - } - - foreach (CustomAttributeData customAttribute in field.CustomAttributes) - { - object attributeValue = customAttribute.ConstructorArguments[0].Value; - - if (Equals(attributeValue, value)) - { - return (string)customAttribute.ConstructorArguments[1].Value; - } - } - - return null; - } - } -} diff --git a/src/ImageSharp46/Profiles/Exif/ExifValue.cs b/src/ImageSharp46/Profiles/Exif/ExifValue.cs deleted file mode 100644 index db62be4c2..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifValue.cs +++ /dev/null @@ -1,716 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Globalization; - using System.Text; - - /// - /// A value of the exif profile. - /// - public sealed class ExifValue : IEquatable - { - private object exifValue; - - /// - /// Initializes a new instance of the class - /// by making a copy from another exif value. - /// - /// The other exif value, where the clone should be made from. - /// is null. - public ExifValue(ExifValue other) - { - Guard.NotNull(other, nameof(other)); - - this.DataType = other.DataType; - this.IsArray = other.IsArray; - this.Tag = other.Tag; - - if (!other.IsArray) - { - this.exifValue = other.exifValue; - } - else - { - Array array = (Array)other.exifValue; - this.exifValue = array.Clone(); - } - } - - /// - /// Gets the data type of the exif value. - /// - public ExifDataType DataType - { - get; - } - - /// - /// Gets a value indicating whether the value is an array. - /// - public bool IsArray - { - get; - } - - /// - /// Gets the tag of the exif value. - /// - public ExifTag Tag - { - get; - } - - /// - /// Gets or sets the value. - /// - public object Value - { - get - { - return this.exifValue; - } - set - { - this.CheckValue(value); - this.exifValue = value; - } - } - - /// - /// Determines whether the specified ExifValue instances are considered equal. - /// - /// The first ExifValue to compare. - /// The second ExifValue to compare. - /// - public static bool operator ==(ExifValue left, ExifValue right) - { - return Equals(left, right); - } - - /// - /// Determines whether the specified ExifValue instances are not considered equal. - /// - /// The first ExifValue to compare. - /// The second ExifValue to compare. - /// - public static bool operator !=(ExifValue left, ExifValue right) - { - return !Equals(left, right); - } - - /// - /// Determines whether the specified object is equal to the current exif value. - /// - /// The object to compare this exif value with. - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) - { - return true; - } - - return this.Equals(obj as ExifValue); - } - - /// - /// Determines whether the specified exif value is equal to the current exif value. - /// - /// The exif value to compare this exif value with. - public bool Equals(ExifValue other) - { - if (ReferenceEquals(other, null)) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - return - this.Tag == other.Tag && - this.DataType == other.DataType && - Equals(this.exifValue, other.exifValue); - } - - /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.exifValue == null) - { - return null; - } - - if (this.DataType == ExifDataType.Ascii) - { - return (string)this.exifValue; - } - - if (!this.IsArray) - { - return this.ToString(this.exifValue); - } - - StringBuilder sb = new StringBuilder(); - foreach (object value in (Array)this.exifValue) - { - sb.Append(this.ToString(value)); - sb.Append(" "); - } - - return sb.ToString(); - } - - internal bool HasValue - { - get - { - if (this.exifValue == null) - { - return false; - } - - if (this.DataType == ExifDataType.Ascii) - { - return ((string)this.exifValue).Length > 0; - } - - return true; - } - } - - internal int Length - { - get - { - if (this.exifValue == null) - { - return 4; - } - - int size = (int)(GetSize(this.DataType) * this.NumberOfComponents); - - return size < 4 ? 4 : size; - } - } - - internal int NumberOfComponents - { - get - { - if (this.DataType == ExifDataType.Ascii) - { - return Encoding.UTF8.GetBytes((string)this.exifValue).Length; - } - - if (this.IsArray) - { - return ((Array)this.exifValue).Length; - } - - return 1; - } - } - - internal ExifValue(ExifTag tag, ExifDataType dataType, bool isArray) - { - this.Tag = tag; - this.DataType = dataType; - this.IsArray = isArray; - - if (dataType == ExifDataType.Ascii) - { - this.IsArray = false; - } - } - - internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray) - : this(tag, dataType, isArray) - { - this.exifValue = value; - } - - internal static ExifValue Create(ExifTag tag, object value) - { - Guard.IsFalse(tag == ExifTag.Unknown, nameof(tag), "Invalid Tag"); - - ExifValue exifValue; - Type type = value?.GetType(); - if (type != null && type.IsArray) - { - type = type.GetElementType(); - } - - switch (tag) - { - case ExifTag.ImageDescription: - case ExifTag.Make: - case ExifTag.Model: - case ExifTag.Software: - case ExifTag.DateTime: - case ExifTag.Artist: - case ExifTag.HostComputer: - case ExifTag.Copyright: - case ExifTag.DocumentName: - case ExifTag.PageName: - case ExifTag.InkNames: - case ExifTag.TargetPrinter: - case ExifTag.ImageID: - case ExifTag.MDLabName: - case ExifTag.MDSampleInfo: - case ExifTag.MDPrepDate: - case ExifTag.MDPrepTime: - case ExifTag.MDFileUnits: - case ExifTag.SEMInfo: - case ExifTag.SpectralSensitivity: - case ExifTag.DateTimeOriginal: - case ExifTag.DateTimeDigitized: - case ExifTag.SubsecTime: - case ExifTag.SubsecTimeOriginal: - case ExifTag.SubsecTimeDigitized: - case ExifTag.FaxSubaddress: - case ExifTag.OffsetTime: - case ExifTag.OffsetTimeOriginal: - case ExifTag.OffsetTimeDigitized: - case ExifTag.SecurityClassification: - case ExifTag.ImageHistory: - case ExifTag.ImageUniqueID: - case ExifTag.OwnerName: - case ExifTag.SerialNumber: - case ExifTag.LensMake: - case ExifTag.LensModel: - case ExifTag.LensSerialNumber: - case ExifTag.GDALMetadata: - case ExifTag.GDALNoData: - case ExifTag.GPSLatitudeRef: - case ExifTag.GPSLongitudeRef: - case ExifTag.GPSSatellites: - case ExifTag.GPSStatus: - case ExifTag.GPSMeasureMode: - case ExifTag.GPSSpeedRef: - case ExifTag.GPSTrackRef: - case ExifTag.GPSImgDirectionRef: - case ExifTag.GPSMapDatum: - case ExifTag.GPSDestLatitudeRef: - case ExifTag.GPSDestLongitudeRef: - case ExifTag.GPSDestBearingRef: - case ExifTag.GPSDestDistanceRef: - case ExifTag.GPSDateStamp: - exifValue = new ExifValue(tag, ExifDataType.Ascii, true); - break; - - case ExifTag.ClipPath: - case ExifTag.VersionYear: - case ExifTag.XMP: - case ExifTag.CFAPattern2: - case ExifTag.TIFFEPStandardID: - case ExifTag.XPTitle: - case ExifTag.XPComment: - case ExifTag.XPAuthor: - case ExifTag.XPKeywords: - case ExifTag.XPSubject: - case ExifTag.GPSVersionID: - exifValue = new ExifValue(tag, ExifDataType.Byte, true); - break; - case ExifTag.FaxProfile: - case ExifTag.ModeNumber: - case ExifTag.GPSAltitudeRef: - exifValue = new ExifValue(tag, ExifDataType.Byte, false); - break; - - case ExifTag.FreeOffsets: - case ExifTag.FreeByteCounts: - case ExifTag.ColorResponseUnit: - case ExifTag.TileOffsets: - case ExifTag.SMinSampleValue: - case ExifTag.SMaxSampleValue: - case ExifTag.JPEGQTables: - case ExifTag.JPEGDCTables: - case ExifTag.JPEGACTables: - case ExifTag.StripRowCounts: - case ExifTag.IntergraphRegisters: - case ExifTag.TimeZoneOffset: - exifValue = new ExifValue(tag, ExifDataType.Long, true); - break; - case ExifTag.SubfileType: - case ExifTag.SubIFDOffset: - case ExifTag.GPSIFDOffset: - case ExifTag.T4Options: - case ExifTag.T6Options: - case ExifTag.XClipPathUnits: - case ExifTag.YClipPathUnits: - case ExifTag.ProfileType: - case ExifTag.CodingMethods: - case ExifTag.T82ptions: - case ExifTag.JPEGInterchangeFormat: - case ExifTag.JPEGInterchangeFormatLength: - case ExifTag.MDFileTag: - case ExifTag.StandardOutputSensitivity: - case ExifTag.RecommendedExposureIndex: - case ExifTag.ISOSpeed: - case ExifTag.ISOSpeedLatitudeyyy: - case ExifTag.ISOSpeedLatitudezzz: - case ExifTag.FaxRecvParams: - case ExifTag.FaxRecvTime: - case ExifTag.ImageNumber: - exifValue = new ExifValue(tag, ExifDataType.Long, false); - break; - - case ExifTag.WhitePoint: - case ExifTag.PrimaryChromaticities: - case ExifTag.YCbCrCoefficients: - case ExifTag.ReferenceBlackWhite: - case ExifTag.PixelScale: - case ExifTag.IntergraphMatrix: - case ExifTag.ModelTiePoint: - case ExifTag.ModelTransform: - case ExifTag.GPSLatitude: - case ExifTag.GPSLongitude: - case ExifTag.GPSTimestamp: - case ExifTag.GPSDestLatitude: - case ExifTag.GPSDestLongitude: - exifValue = new ExifValue(tag, ExifDataType.Rational, true); - break; - case ExifTag.XPosition: - case ExifTag.YPosition: - case ExifTag.XResolution: - case ExifTag.YResolution: - case ExifTag.BatteryLevel: - case ExifTag.ExposureTime: - case ExifTag.FNumber: - case ExifTag.MDScalePixel: - case ExifTag.CompressedBitsPerPixel: - case ExifTag.ApertureValue: - case ExifTag.MaxApertureValue: - case ExifTag.SubjectDistance: - case ExifTag.FocalLength: - case ExifTag.FlashEnergy2: - case ExifTag.FocalPlaneXResolution2: - case ExifTag.FocalPlaneYResolution2: - case ExifTag.ExposureIndex2: - case ExifTag.Humidity: - case ExifTag.Pressure: - case ExifTag.Acceleration: - case ExifTag.FlashEnergy: - case ExifTag.FocalPlaneXResolution: - case ExifTag.FocalPlaneYResolution: - case ExifTag.ExposureIndex: - case ExifTag.DigitalZoomRatio: - case ExifTag.LensInfo: - case ExifTag.GPSAltitude: - case ExifTag.GPSDOP: - case ExifTag.GPSSpeed: - case ExifTag.GPSTrack: - case ExifTag.GPSImgDirection: - case ExifTag.GPSDestBearing: - case ExifTag.GPSDestDistance: - exifValue = new ExifValue(tag, ExifDataType.Rational, false); - break; - - case ExifTag.BitsPerSample: - case ExifTag.MinSampleValue: - case ExifTag.MaxSampleValue: - case ExifTag.GrayResponseCurve: - case ExifTag.ColorMap: - case ExifTag.ExtraSamples: - case ExifTag.PageNumber: - case ExifTag.TransferFunction: - case ExifTag.Predictor: - case ExifTag.HalftoneHints: - case ExifTag.SampleFormat: - case ExifTag.TransferRange: - case ExifTag.DefaultImageColor: - case ExifTag.JPEGLosslessPredictors: - case ExifTag.JPEGPointTransforms: - case ExifTag.YCbCrSubsampling: - case ExifTag.CFARepeatPatternDim: - case ExifTag.IntergraphPacketData: - case ExifTag.ISOSpeedRatings: - case ExifTag.SubjectArea: - case ExifTag.SubjectLocation: - exifValue = new ExifValue(tag, ExifDataType.Short, true); - break; - case ExifTag.OldSubfileType: - case ExifTag.Compression: - case ExifTag.PhotometricInterpretation: - case ExifTag.Thresholding: - case ExifTag.CellWidth: - case ExifTag.CellLength: - case ExifTag.FillOrder: - case ExifTag.Orientation: - case ExifTag.SamplesPerPixel: - case ExifTag.PlanarConfiguration: - case ExifTag.GrayResponseUnit: - case ExifTag.ResolutionUnit: - case ExifTag.CleanFaxData: - case ExifTag.InkSet: - case ExifTag.NumberOfInks: - case ExifTag.DotRange: - case ExifTag.Indexed: - case ExifTag.OPIProxy: - case ExifTag.JPEGProc: - case ExifTag.JPEGRestartInterval: - case ExifTag.YCbCrPositioning: - case ExifTag.Rating: - case ExifTag.RatingPercent: - case ExifTag.ExposureProgram: - case ExifTag.Interlace: - case ExifTag.SelfTimerMode: - case ExifTag.SensitivityType: - case ExifTag.MeteringMode: - case ExifTag.LightSource: - case ExifTag.FocalPlaneResolutionUnit2: - case ExifTag.SensingMethod2: - case ExifTag.Flash: - case ExifTag.ColorSpace: - case ExifTag.FocalPlaneResolutionUnit: - case ExifTag.SensingMethod: - case ExifTag.CustomRendered: - case ExifTag.ExposureMode: - case ExifTag.WhiteBalance: - case ExifTag.FocalLengthIn35mmFilm: - case ExifTag.SceneCaptureType: - case ExifTag.GainControl: - case ExifTag.Contrast: - case ExifTag.Saturation: - case ExifTag.Sharpness: - case ExifTag.SubjectDistanceRange: - case ExifTag.GPSDifferential: - exifValue = new ExifValue(tag, ExifDataType.Short, false); - break; - - case ExifTag.Decode: - exifValue = new ExifValue(tag, ExifDataType.SignedRational, true); - break; - case ExifTag.ShutterSpeedValue: - case ExifTag.BrightnessValue: - case ExifTag.ExposureBiasValue: - case ExifTag.AmbientTemperature: - case ExifTag.WaterDepth: - case ExifTag.CameraElevationAngle: - exifValue = new ExifValue(tag, ExifDataType.SignedRational, false); - break; - - case ExifTag.JPEGTables: - case ExifTag.OECF: - case ExifTag.ExifVersion: - case ExifTag.ComponentsConfiguration: - case ExifTag.MakerNote: - case ExifTag.UserComment: - case ExifTag.FlashpixVersion: - case ExifTag.SpatialFrequencyResponse: - case ExifTag.SpatialFrequencyResponse2: - case ExifTag.Noise: - case ExifTag.CFAPattern: - case ExifTag.DeviceSettingDescription: - case ExifTag.ImageSourceData: - case ExifTag.GPSProcessingMethod: - case ExifTag.GPSAreaInformation: - exifValue = new ExifValue(tag, ExifDataType.Undefined, true); - break; - case ExifTag.FileSource: - case ExifTag.SceneType: - exifValue = new ExifValue(tag, ExifDataType.Undefined, false); - break; - - case ExifTag.StripOffsets: - case ExifTag.TileByteCounts: - case ExifTag.ImageLayer: - exifValue = CreateNumber(tag, type, true); - break; - case ExifTag.ImageWidth: - case ExifTag.ImageLength: - case ExifTag.TileWidth: - case ExifTag.TileLength: - case ExifTag.BadFaxLines: - case ExifTag.ConsecutiveBadFaxLines: - case ExifTag.PixelXDimension: - case ExifTag.PixelYDimension: - exifValue = CreateNumber(tag, type, false); - break; - - default: - throw new NotSupportedException(); - } - - exifValue.Value = value; - return exifValue; - } - - internal static uint GetSize(ExifDataType dataType) - { - switch (dataType) - { - case ExifDataType.Ascii: - case ExifDataType.Byte: - case ExifDataType.SignedByte: - case ExifDataType.Undefined: - return 1; - case ExifDataType.Short: - case ExifDataType.SignedShort: - return 2; - case ExifDataType.Long: - case ExifDataType.SignedLong: - case ExifDataType.SingleFloat: - return 4; - case ExifDataType.DoubleFloat: - case ExifDataType.Rational: - case ExifDataType.SignedRational: - return 8; - default: - throw new NotSupportedException(dataType.ToString()); - } - } - - private void CheckValue(object value) - { - if (value == null) - { - return; - } - - Type type = value.GetType(); - - if (this.DataType == ExifDataType.Ascii) - { - Guard.IsTrue(type == typeof(string), nameof(value), "Value should be a string."); - return; - } - - if (type.IsArray) - { - Guard.IsTrue(this.IsArray, nameof(value), "Value should not be an array."); - type = type.GetElementType(); - } - else - { - Guard.IsFalse(this.IsArray, nameof(value), "Value should not be an array."); - } - - switch (this.DataType) - { - case ExifDataType.Byte: - Guard.IsTrue(type == typeof(byte), nameof(value), $"Value should be a byte{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.DoubleFloat: - Guard.IsTrue(type == typeof(double), nameof(value), $"Value should be a double{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.Long: - Guard.IsTrue(type == typeof(uint), nameof(value), $"Value should be an unsigned int{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.Rational: - Guard.IsTrue(type == typeof(Rational), nameof(value), $"Value should be a Rational{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.Short: - Guard.IsTrue(type == typeof(ushort), nameof(value), $"Value should be an unsigned short{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.SignedByte: - Guard.IsTrue(type == typeof(sbyte), nameof(value), $"Value should be a signed byte{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.SignedLong: - Guard.IsTrue(type == typeof(int), nameof(value), $"Value should be an int{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.SignedRational: - Guard.IsTrue(type == typeof(SignedRational), nameof(value), $"Value should be a SignedRational{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.SignedShort: - Guard.IsTrue(type == typeof(short), nameof(value), $"Value should be a short{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.SingleFloat: - Guard.IsTrue(type == typeof(float), nameof(value), $"Value should be a float{(this.IsArray ? " array." : ".")}"); - break; - case ExifDataType.Undefined: - Guard.IsTrue(type == typeof(byte), nameof(value), "Value should be a byte array."); - break; - default: - throw new NotSupportedException(); - } - } - - private static ExifValue CreateNumber(ExifTag tag, Type type, bool isArray) - { - if (type == null || type == typeof(ushort)) - { - return new ExifValue(tag, ExifDataType.Short, isArray); - } - - if (type == typeof(short)) - { - return new ExifValue(tag, ExifDataType.SignedShort, isArray); - } - - if (type == typeof(uint)) - { - return new ExifValue(tag, ExifDataType.Long, isArray); - } - - return new ExifValue(tag, ExifDataType.SignedLong, isArray); - } - - private string ToString(object value) - { - string description = ExifTagDescriptionAttribute.GetDescription(this.Tag, value); - if (description != null) - { - return description; - } - - switch (this.DataType) - { - case ExifDataType.Ascii: - return (string)value; - case ExifDataType.Byte: - return ((byte)value).ToString("X2", CultureInfo.InvariantCulture); - case ExifDataType.DoubleFloat: - return ((double)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.Long: - return ((uint)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.Rational: - return ((Rational)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.Short: - return ((ushort)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.SignedByte: - return ((sbyte)value).ToString("X2", CultureInfo.InvariantCulture); - case ExifDataType.SignedLong: - return ((int)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.SignedRational: - return ((Rational)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.SignedShort: - return ((short)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.SingleFloat: - return ((float)value).ToString(CultureInfo.InvariantCulture); - case ExifDataType.Undefined: - return ((byte)value).ToString("X2", CultureInfo.InvariantCulture); - default: - throw new NotSupportedException(); - } - } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(ExifValue exif) - { - int hashCode = exif.Tag.GetHashCode() ^ exif.DataType.GetHashCode(); - return hashCode ^ exif.exifValue?.GetHashCode() ?? hashCode; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/ExifWriter.cs b/src/ImageSharp46/Profiles/Exif/ExifWriter.cs deleted file mode 100644 index f7653b240..000000000 --- a/src/ImageSharp46/Profiles/Exif/ExifWriter.cs +++ /dev/null @@ -1,585 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Text; - - internal sealed class ExifWriter - { - private static readonly ExifTag[] IfdTags = new ExifTag[127] - { - ExifTag.SubfileType, - ExifTag.OldSubfileType, - ExifTag.ImageWidth, - ExifTag.ImageLength, - ExifTag.BitsPerSample, - ExifTag.Compression, - ExifTag.PhotometricInterpretation, - ExifTag.Thresholding, - ExifTag.CellWidth, - ExifTag.CellLength, - ExifTag.FillOrder, - ExifTag.DocumentName, - ExifTag.ImageDescription, - ExifTag.Make, - ExifTag.Model, - ExifTag.StripOffsets, - ExifTag.Orientation, - ExifTag.SamplesPerPixel, - ExifTag.RowsPerStrip, - ExifTag.StripByteCounts, - ExifTag.MinSampleValue, - ExifTag.MaxSampleValue, - ExifTag.XResolution, - ExifTag.YResolution, - ExifTag.PlanarConfiguration, - ExifTag.PageName, - ExifTag.XPosition, - ExifTag.YPosition, - ExifTag.FreeOffsets, - ExifTag.FreeByteCounts, - ExifTag.GrayResponseUnit, - ExifTag.GrayResponseCurve, - ExifTag.T4Options, - ExifTag.T6Options, - ExifTag.ResolutionUnit, - ExifTag.PageNumber, - ExifTag.ColorResponseUnit, - ExifTag.TransferFunction, - ExifTag.Software, - ExifTag.DateTime, - ExifTag.Artist, - ExifTag.HostComputer, - ExifTag.Predictor, - ExifTag.WhitePoint, - ExifTag.PrimaryChromaticities, - ExifTag.ColorMap, - ExifTag.HalftoneHints, - ExifTag.TileWidth, - ExifTag.TileLength, - ExifTag.TileOffsets, - ExifTag.TileByteCounts, - ExifTag.BadFaxLines, - ExifTag.CleanFaxData, - ExifTag.ConsecutiveBadFaxLines, - ExifTag.InkSet, - ExifTag.InkNames, - ExifTag.NumberOfInks, - ExifTag.DotRange, - ExifTag.TargetPrinter, - ExifTag.ExtraSamples, - ExifTag.SampleFormat, - ExifTag.SMinSampleValue, - ExifTag.SMaxSampleValue, - ExifTag.TransferRange, - ExifTag.ClipPath, - ExifTag.XClipPathUnits, - ExifTag.YClipPathUnits, - ExifTag.Indexed, - ExifTag.JPEGTables, - ExifTag.OPIProxy, - ExifTag.ProfileType, - ExifTag.FaxProfile, - ExifTag.CodingMethods, - ExifTag.VersionYear, - ExifTag.ModeNumber, - ExifTag.Decode, - ExifTag.DefaultImageColor, - ExifTag.T82ptions, - ExifTag.JPEGProc, - ExifTag.JPEGInterchangeFormat, - ExifTag.JPEGInterchangeFormatLength, - ExifTag.JPEGRestartInterval, - ExifTag.JPEGLosslessPredictors, - ExifTag.JPEGPointTransforms, - ExifTag.JPEGQTables, - ExifTag.JPEGDCTables, - ExifTag.JPEGACTables, - ExifTag.YCbCrCoefficients, - ExifTag.YCbCrSubsampling, - ExifTag.YCbCrSubsampling, - ExifTag.YCbCrPositioning, - ExifTag.ReferenceBlackWhite, - ExifTag.StripRowCounts, - ExifTag.XMP, - ExifTag.Rating, - ExifTag.RatingPercent, - ExifTag.ImageID, - ExifTag.CFARepeatPatternDim, - ExifTag.CFAPattern2, - ExifTag.BatteryLevel, - ExifTag.Copyright, - ExifTag.MDFileTag, - ExifTag.MDScalePixel, - ExifTag.MDLabName, - ExifTag.MDSampleInfo, - ExifTag.MDPrepDate, - ExifTag.MDPrepTime, - ExifTag.MDFileUnits, - ExifTag.PixelScale, - ExifTag.IntergraphPacketData, - ExifTag.IntergraphRegisters, - ExifTag.IntergraphMatrix, - ExifTag.ModelTiePoint, - ExifTag.SEMInfo, - ExifTag.ModelTransform, - ExifTag.ImageLayer, - ExifTag.FaxRecvParams, - ExifTag.FaxSubaddress, - ExifTag.FaxRecvTime, - ExifTag.ImageSourceData, - ExifTag.XPTitle, - ExifTag.XPComment, - ExifTag.XPAuthor, - ExifTag.XPKeywords, - ExifTag.XPSubject, - ExifTag.GDALMetadata, - ExifTag.GDALNoData - }; - - private static readonly ExifTag[] ExifTags = new ExifTag[92] - { - ExifTag.ExposureTime, - ExifTag.FNumber, - ExifTag.ExposureProgram, - ExifTag.SpectralSensitivity, - ExifTag.ISOSpeedRatings, - ExifTag.OECF, - ExifTag.Interlace, - ExifTag.TimeZoneOffset, - ExifTag.SelfTimerMode, - ExifTag.SensitivityType, - ExifTag.StandardOutputSensitivity, - ExifTag.RecommendedExposureIndex, - ExifTag.ISOSpeed, - ExifTag.ISOSpeedLatitudeyyy, - ExifTag.ISOSpeedLatitudezzz, - ExifTag.ExifVersion, - ExifTag.DateTimeOriginal, - ExifTag.DateTimeDigitized, - ExifTag.OffsetTime, - ExifTag.OffsetTimeOriginal, - ExifTag.OffsetTimeDigitized, - ExifTag.ComponentsConfiguration, - ExifTag.CompressedBitsPerPixel, - ExifTag.ShutterSpeedValue, - ExifTag.ApertureValue, - ExifTag.BrightnessValue, - ExifTag.ExposureBiasValue, - ExifTag.MaxApertureValue, - ExifTag.SubjectDistance, - ExifTag.MeteringMode, - ExifTag.LightSource, - ExifTag.Flash, - ExifTag.FocalLength, - ExifTag.FlashEnergy2, - ExifTag.SpatialFrequencyResponse2, - ExifTag.Noise, - ExifTag.FocalPlaneXResolution2, - ExifTag.FocalPlaneYResolution2, - ExifTag.FocalPlaneResolutionUnit2, - ExifTag.ImageNumber, - ExifTag.SecurityClassification, - ExifTag.ImageHistory, - ExifTag.SubjectArea, - ExifTag.ExposureIndex2, - ExifTag.TIFFEPStandardID, - ExifTag.SensingMethod2, - ExifTag.MakerNote, - ExifTag.UserComment, - ExifTag.SubsecTime, - ExifTag.SubsecTimeOriginal, - ExifTag.SubsecTimeDigitized, - ExifTag.AmbientTemperature, - ExifTag.Humidity, - ExifTag.Pressure, - ExifTag.WaterDepth, - ExifTag.Acceleration, - ExifTag.CameraElevationAngle, - ExifTag.FlashpixVersion, - ExifTag.ColorSpace, - ExifTag.PixelXDimension, - ExifTag.PixelYDimension, - ExifTag.RelatedSoundFile, - ExifTag.FlashEnergy, - ExifTag.SpatialFrequencyResponse, - ExifTag.FocalPlaneXResolution, - ExifTag.FocalPlaneYResolution, - ExifTag.FocalPlaneResolutionUnit, - ExifTag.SubjectLocation, - ExifTag.ExposureIndex, - ExifTag.SensingMethod, - ExifTag.FileSource, - ExifTag.SceneType, - ExifTag.CFAPattern, - ExifTag.CustomRendered, - ExifTag.ExposureMode, - ExifTag.WhiteBalance, - ExifTag.DigitalZoomRatio, - ExifTag.FocalLengthIn35mmFilm, - ExifTag.SceneCaptureType, - ExifTag.GainControl, - ExifTag.Contrast, - ExifTag.Saturation, - ExifTag.Sharpness, - ExifTag.DeviceSettingDescription, - ExifTag.SubjectDistanceRange, - ExifTag.ImageUniqueID, - ExifTag.OwnerName, - ExifTag.SerialNumber, - ExifTag.LensInfo, - ExifTag.LensMake, - ExifTag.LensModel, - ExifTag.LensSerialNumber - }; - - private static readonly ExifTag[] GPSTags = new ExifTag[31] - { - ExifTag.GPSVersionID, - ExifTag.GPSLatitudeRef, - ExifTag.GPSLatitude, - ExifTag.GPSLongitudeRef, - ExifTag.GPSLongitude, - ExifTag.GPSAltitudeRef, - ExifTag.GPSAltitude, - ExifTag.GPSTimestamp, - ExifTag.GPSSatellites, - ExifTag.GPSStatus, - ExifTag.GPSMeasureMode, - ExifTag.GPSDOP, - ExifTag.GPSSpeedRef, - ExifTag.GPSSpeed, - ExifTag.GPSTrackRef, - ExifTag.GPSTrack, - ExifTag.GPSImgDirectionRef, - ExifTag.GPSImgDirection, - ExifTag.GPSMapDatum, - ExifTag.GPSDestLatitudeRef, - ExifTag.GPSDestLatitude, - ExifTag.GPSDestLongitudeRef, - ExifTag.GPSDestLongitude, - ExifTag.GPSDestBearingRef, - ExifTag.GPSDestBearing, - ExifTag.GPSDestDistanceRef, - ExifTag.GPSDestDistance, - ExifTag.GPSProcessingMethod, - ExifTag.GPSAreaInformation, - ExifTag.GPSDateStamp, - ExifTag.GPSDifferential - }; - - private const int StartIndex = 6; - - private ExifParts allowedParts; - private Collection values; - private Collection dataOffsets; - private Collection ifdIndexes; - private Collection exifIndexes; - private Collection gpsIndexes; - - public ExifWriter(Collection values, ExifParts allowedParts) - { - this.values = values; - this.allowedParts = allowedParts; - this.ifdIndexes = this.GetIndexes(ExifParts.IfdTags, IfdTags); - this.exifIndexes = this.GetIndexes(ExifParts.ExifTags, ExifTags); - this.gpsIndexes = this.GetIndexes(ExifParts.GPSTags, GPSTags); - } - - public byte[] GetData() - { - uint length = 0; - int exifIndex = -1; - int gpsIndex = -1; - - if (this.exifIndexes.Count > 0) - { - exifIndex = (int)this.GetIndex(this.ifdIndexes, ExifTag.SubIFDOffset); - } - - if (this.gpsIndexes.Count > 0) - { - gpsIndex = (int)this.GetIndex(this.ifdIndexes, ExifTag.GPSIFDOffset); - } - - uint ifdLength = 2 + this.GetLength(this.ifdIndexes) + 4; - uint exifLength = this.GetLength(this.exifIndexes); - uint gpsLength = this.GetLength(this.gpsIndexes); - - if (exifLength > 0) - { - exifLength += 2; - } - - if (gpsLength > 0) - { - gpsLength += 2; - } - - length = ifdLength + exifLength + gpsLength; - - if (length == 6) - { - return null; - } - - length += 10 + 4 + 2; - - byte[] result = new byte[length]; - result[0] = (byte)'E'; - result[1] = (byte)'x'; - result[2] = (byte)'i'; - result[3] = (byte)'f'; - result[4] = 0x00; - result[5] = 0x00; - result[6] = (byte)'I'; - result[7] = (byte)'I'; - result[8] = 0x2A; - result[9] = 0x00; - - int i = 10; - uint ifdOffset = ((uint)i - StartIndex) + 4; - uint thumbnailOffset = ifdOffset + ifdLength + exifLength + gpsLength; - - if (exifLength > 0) - { - this.values[exifIndex].Value = ifdOffset + ifdLength; - } - - if (gpsLength > 0) - { - this.values[gpsIndex].Value = ifdOffset + ifdLength + exifLength; - } - - i = Write(BitConverter.GetBytes(ifdOffset), result, i); - i = this.WriteHeaders(this.ifdIndexes, result, i); - i = Write(BitConverter.GetBytes(thumbnailOffset), result, i); - i = this.WriteData(this.ifdIndexes, result, i); - - if (exifLength > 0) - { - i = this.WriteHeaders(this.exifIndexes, result, i); - i = this.WriteData(this.exifIndexes, result, i); - } - - if (gpsLength > 0) - { - i = this.WriteHeaders(this.gpsIndexes, result, i); - i = this.WriteData(this.gpsIndexes, result, i); - } - - Write(BitConverter.GetBytes((ushort)0), result, i); - - return result; - } - - private int GetIndex(Collection indexes, ExifTag tag) - { - foreach (int index in indexes) - { - if (this.values[index].Tag == tag) - { - return index; - } - } - - int newIndex = this.values.Count; - indexes.Add(newIndex); - this.values.Add(ExifValue.Create(tag, null)); - return newIndex; - } - - private Collection GetIndexes(ExifParts part, ExifTag[] tags) - { - if (((int)this.allowedParts & (int)part) == 0) - { - return new Collection(); - } - - Collection result = new Collection(); - for (int i = 0; i < this.values.Count; i++) - { - ExifValue value = this.values[i]; - - if (!value.HasValue) - { - continue; - } - - int index = Array.IndexOf(tags, value.Tag); - if (index > -1) - { - result.Add(i); - } - } - - return result; - } - - private uint GetLength(IEnumerable indexes) - { - uint length = 0; - - foreach (int index in indexes) - { - uint valueLength = (uint)this.values[index].Length; - - if (valueLength > 4) - { - length += 12 + valueLength; - } - else - { - length += 12; - } - } - - return length; - } - - private static int Write(byte[] source, byte[] destination, int offset) - { - Buffer.BlockCopy(source, 0, destination, offset, source.Length); - - return offset + source.Length; - } - - private int WriteArray(ExifValue value, byte[] destination, int offset) - { - if (value.DataType == ExifDataType.Ascii) - { - return this.WriteValue(ExifDataType.Ascii, value.Value, destination, offset); - } - - int newOffset = offset; - foreach (object obj in (Array)value.Value) - { - newOffset = this.WriteValue(value.DataType, obj, destination, newOffset); - } - - return newOffset; - } - - private int WriteData(Collection indexes, byte[] destination, int offset) - { - if (this.dataOffsets.Count == 0) - { - return offset; - } - - int newOffset = offset; - - int i = 0; - foreach (int index in indexes) - { - ExifValue value = this.values[index]; - if (value.Length > 4) - { - Write(BitConverter.GetBytes(newOffset - StartIndex), destination, this.dataOffsets[i++]); - newOffset = this.WriteValue(value, destination, newOffset); - } - } - - return newOffset; - } - - private int WriteHeaders(Collection indexes, byte[] destination, int offset) - { - this.dataOffsets = new Collection(); - - int newOffset = Write(BitConverter.GetBytes((ushort)indexes.Count), destination, offset); - - if (indexes.Count == 0) - { - return newOffset; - } - - foreach (int index in indexes) - { - ExifValue value = this.values[index]; - newOffset = Write(BitConverter.GetBytes((ushort)value.Tag), destination, newOffset); - newOffset = Write(BitConverter.GetBytes((ushort)value.DataType), destination, newOffset); - newOffset = Write(BitConverter.GetBytes((uint)value.NumberOfComponents), destination, newOffset); - - if (value.Length > 4) - { - this.dataOffsets.Add(newOffset); - } - else - { - this.WriteValue(value, destination, newOffset); - } - - newOffset += 4; - } - - return newOffset; - } - - private int WriteRational(Rational value, byte[] destination, int offset) - { - Write(BitConverter.GetBytes(value.Numerator), destination, offset); - Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4); - - return offset + 8; - } - - private int WriteSignedRational(SignedRational value, byte[] destination, int offset) - { - Write(BitConverter.GetBytes(value.Numerator), destination, offset); - Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4); - - return offset + 8; - } - - private int WriteValue(ExifDataType dataType, object value, byte[] destination, int offset) - { - switch (dataType) - { - case ExifDataType.Ascii: - return Write(Encoding.UTF8.GetBytes((string)value), destination, offset); - case ExifDataType.Byte: - case ExifDataType.Undefined: - destination[offset] = (byte)value; - return offset + 1; - case ExifDataType.DoubleFloat: - return Write(BitConverter.GetBytes((double)value), destination, offset); - case ExifDataType.Short: - return Write(BitConverter.GetBytes((ushort)value), destination, offset); - case ExifDataType.Long: - return Write(BitConverter.GetBytes((uint)value), destination, offset); - case ExifDataType.Rational: - return this.WriteRational((Rational)value, destination, offset); - case ExifDataType.SignedByte: - destination[offset] = unchecked((byte)((sbyte)value)); - return offset + 1; - case ExifDataType.SignedLong: - return Write(BitConverter.GetBytes((int)value), destination, offset); - case ExifDataType.SignedShort: - return Write(BitConverter.GetBytes((short)value), destination, offset); - case ExifDataType.SignedRational: - return this.WriteSignedRational((SignedRational)value, destination, offset); - case ExifDataType.SingleFloat: - return Write(BitConverter.GetBytes((float)value), destination, offset); - default: - throw new NotImplementedException(); - } - } - - private int WriteValue(ExifValue value, byte[] destination, int offset) - { - if (value.IsArray && value.DataType != ExifDataType.Ascii) - { - return this.WriteArray(value, destination, offset); - } - - return this.WriteValue(value.DataType, value.Value, destination, offset); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Profiles/Exif/README.md b/src/ImageSharp46/Profiles/Exif/README.md deleted file mode 100644 index b6e27b70c..000000000 --- a/src/ImageSharp46/Profiles/Exif/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Adapted from Magick.NET: - -https://github.com/dlemstra/Magick.NET/tree/784e23b1f5c824fc03d4b95d3387b3efe1ed510b/Magick.NET/Core/Profiles/Exif \ No newline at end of file diff --git a/src/ImageSharp46/ProgressEventArgs.cs b/src/ImageSharp46/ProgressEventArgs.cs deleted file mode 100644 index 585dd1b63..000000000 --- a/src/ImageSharp46/ProgressEventArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Contains event data related to the progress made processing an image. - /// - public class ProgressEventArgs : System.EventArgs - { - /// - /// Gets or sets the number of rows processed. - /// - public int RowsProcessed { get; set; } - - /// - /// Gets or sets the total number of rows. - /// - public int TotalRows { get; set; } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Properties/AssemblyInfo.cs b/src/ImageSharp46/Properties/AssemblyInfo.cs deleted file mode 100644 index ec405e1d0..000000000 --- a/src/ImageSharp46/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ImageSharp")] -[assembly: AssemblyDescription("A cross-platform library for processing of image files; written in C#")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("James Jackson-South")] -[assembly: AssemblyProduct("ImageSharp")] -[assembly: AssemblyCopyright("Copyright (c) James Jackson-South and contributors.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0.0")] - -// Ensure the internals can be tested. -[assembly: InternalsVisibleTo("ImageSharp.Benchmarks")] -[assembly: InternalsVisibleTo("ImageSharp.Tests")] diff --git a/src/ImageSharp46/Quantizers/IQuantizer.cs b/src/ImageSharp46/Quantizers/IQuantizer.cs deleted file mode 100644 index 8b92af125..000000000 --- a/src/ImageSharp46/Quantizers/IQuantizer.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - /// - /// Provides methods for allowing quantization of images pixels. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IQuantizer : IQuantizer - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Quantize an image and return the resulting output pixels. - /// - /// The image to quantize. - /// The maximum number of colors to return. - /// - /// A representing a quantized version of the image pixels. - /// - QuantizedImage Quantize(ImageBase image, int maxColors); - } - - /// - /// Provides methods for allowing quantization of images pixels. - /// - public interface IQuantizer - { - } -} diff --git a/src/ImageSharp46/Quantizers/Octree/OctreeQuantizer.cs b/src/ImageSharp46/Quantizers/Octree/OctreeQuantizer.cs deleted file mode 100644 index 5e06a721e..000000000 --- a/src/ImageSharp46/Quantizers/Octree/OctreeQuantizer.cs +++ /dev/null @@ -1,518 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - using System; - using System.Collections.Generic; - - /// - /// Encapsulates methods to calculate the colour palette if an image using an Octree pattern. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - public sealed class OctreeQuantizer : Quantizer - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Stores the tree - /// - private Octree octree; - - /// - /// Maximum allowed color depth - /// - private int colors; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The Octree quantizer is a two pass algorithm. The initial pass sets up the Octree, - /// the second pass quantizes a color based on the nodes in the tree - /// - public OctreeQuantizer() - : base(false) - { - } - - /// - public override QuantizedImage Quantize(ImageBase image, int maxColors) - { - this.colors = maxColors.Clamp(1, 256); - - if (this.octree == null) - { - // Construct the Octree - this.octree = new Octree(this.GetBitsNeededForColorDepth(maxColors)); - } - - return base.Quantize(image, maxColors); - } - - /// - /// Process the pixel in the first pass of the algorithm - /// - /// - /// The pixel to quantize - /// - /// - /// This function need only be overridden if your quantize algorithm needs two passes, - /// such as an Octree quantizer. - /// - protected override void InitialQuantizePixel(TColor pixel) - { - // Add the color to the Octree - this.octree.AddColor(pixel); - } - - /// - /// Override this to process the pixel in the second pass of the algorithm - /// - /// The pixel to quantize - /// - /// The quantized value - /// - protected override byte QuantizePixel(TColor pixel) - { - return (byte)this.octree.GetPaletteIndex(pixel); - } - - /// - /// Retrieve the palette for the quantized image. - /// - /// - /// The new color palette - /// - protected override List GetPalette() - { - return this.octree.Palletize(Math.Max(this.colors, 1)); - } - - /// - /// Returns how many bits are required to store the specified number of colors. - /// Performs a Log2() on the value. - /// - /// The number of colors. - /// - /// The - /// - private int GetBitsNeededForColorDepth(int colorCount) - { - return (int)Math.Ceiling(Math.Log(colorCount, 2)); - } - - /// - /// Class which does the actual quantization - /// - private class Octree - { - /// - /// Mask used when getting the appropriate pixels for a given node - /// - private static readonly int[] Mask = { 0x100, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - - /// - /// The root of the Octree - /// - private readonly OctreeNode root; - - /// - /// Array of reducible nodes - /// - private readonly OctreeNode[] reducibleNodes; - - /// - /// Maximum number of significant bits in the image - /// - private readonly int maxColorBits; - - /// - /// Store the last node quantized - /// - private OctreeNode previousNode; - - /// - /// Cache the previous color quantized - /// - private TPacked previousColor; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The maximum number of significant bits in the image - /// - public Octree(int maxColorBits) - { - this.maxColorBits = maxColorBits; - this.Leaves = 0; - this.reducibleNodes = new OctreeNode[9]; - this.root = new OctreeNode(0, this.maxColorBits, this); - this.previousColor = default(TPacked); - this.previousNode = null; - } - - /// - /// Gets or sets the number of leaves in the tree - /// - private int Leaves { get; set; } - - /// - /// Gets the array of reducible nodes - /// - private OctreeNode[] ReducibleNodes => this.reducibleNodes; - - /// - /// Add a given color value to the Octree - /// - /// - /// The containing color information to add. - /// - public void AddColor(TColor pixel) - { - TPacked packed = pixel.PackedValue; - - // Check if this request is for the same color as the last - if (this.previousColor.Equals(packed)) - { - // If so, check if I have a previous node setup. This will only occur if the first color in the image - // happens to be black, with an alpha component of zero. - if (this.previousNode == null) - { - this.previousColor = packed; - this.root.AddColor(pixel, this.maxColorBits, 0, this); - } - else - { - // Just update the previous node - this.previousNode.Increment(pixel); - } - } - else - { - this.previousColor = packed; - this.root.AddColor(pixel, this.maxColorBits, 0, this); - } - } - - /// - /// Convert the nodes in the Octree to a palette with a maximum of colorCount colors - /// - /// The maximum number of colors - /// - /// An with the palletized colors - /// - public List Palletize(int colorCount) - { - while (this.Leaves > colorCount) - { - this.Reduce(); - } - - // Now palletize the nodes - List palette = new List(this.Leaves); - int paletteIndex = 0; - this.root.ConstructPalette(palette, ref paletteIndex); - - // And return the palette - return palette; - } - - /// - /// Get the palette index for the passed color - /// - /// The containing the pixel data. - /// - /// The index of the given structure. - /// - public int GetPaletteIndex(TColor pixel) - { - return this.root.GetPaletteIndex(pixel, 0); - } - - /// - /// Keep track of the previous node that was quantized - /// - /// - /// The node last quantized - /// - protected void TrackPrevious(OctreeNode node) - { - this.previousNode = node; - } - - /// - /// Reduce the depth of the tree - /// - private void Reduce() - { - // Find the deepest level containing at least one reducible node - int index = this.maxColorBits - 1; - while ((index > 0) && (this.reducibleNodes[index] == null)) - { - index--; - } - - // Reduce the node most recently added to the list at level 'index' - OctreeNode node = this.reducibleNodes[index]; - this.reducibleNodes[index] = node.NextReducible; - - // Decrement the leaf count after reducing the node - this.Leaves -= node.Reduce(); - - // And just in case I've reduced the last color to be added, and the next color to - // be added is the same, invalidate the previousNode... - this.previousNode = null; - } - - /// - /// Class which encapsulates each node in the tree - /// - protected class OctreeNode - { - /// - /// Pointers to any child nodes - /// - private readonly OctreeNode[] children; - - /// - /// Flag indicating that this is a leaf node - /// - private bool leaf; - - /// - /// Number of pixels in this node - /// - private int pixelCount; - - /// - /// Red component - /// - private int red; - - /// - /// Green Component - /// - private int green; - - /// - /// Blue component - /// - private int blue; - - /// - /// Alpha component - /// - private int alpha; - - /// - /// The index of this node in the palette - /// - private int paletteIndex; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The level in the tree = 0 - 7 - /// - /// - /// The number of significant color bits in the image - /// - /// - /// The tree to which this node belongs - /// - public OctreeNode(int level, int colorBits, Octree octree) - { - // Construct the new node - this.leaf = level == colorBits; - - this.red = this.green = this.blue = this.alpha = 0; - this.pixelCount = 0; - - // If a leaf, increment the leaf count - if (this.leaf) - { - octree.Leaves++; - this.NextReducible = null; - this.children = null; - } - else - { - // Otherwise add this to the reducible nodes - this.NextReducible = octree.ReducibleNodes[level]; - octree.ReducibleNodes[level] = this; - this.children = new OctreeNode[8]; - } - } - - /// - /// Gets the next reducible node - /// - public OctreeNode NextReducible { get; } - - /// - /// Add a color into the tree - /// - /// The color - /// The number of significant color bits - /// The level in the tree - /// The tree to which this node belongs - public void AddColor(TColor pixel, int colorBits, int level, Octree octree) - { - // Update the color information if this is a leaf - if (this.leaf) - { - this.Increment(pixel); - - // Setup the previous node - octree.TrackPrevious(this); - } - else - { - // Go to the next level down in the tree - int shift = 7 - level; - Color color = new Color(pixel.ToVector4()); - int index = ((color.A & Mask[0]) >> (shift - 3)) | - ((color.B & Mask[level + 1]) >> (shift - 2)) | - ((color.G & Mask[level + 1]) >> (shift - 1)) | - ((color.R & Mask[level + 1]) >> shift); - - OctreeNode child = this.children[index]; - - if (child == null) - { - // Create a new child node and store it in the array - child = new OctreeNode(level + 1, colorBits, octree); - this.children[index] = child; - } - - // Add the color to the child node - child.AddColor(pixel, colorBits, level + 1, octree); - } - } - - /// - /// Reduce this node by removing all of its children - /// - /// The number of leaves removed - public int Reduce() - { - this.red = this.green = this.blue = this.alpha = 0; - int childNodes = 0; - - // Loop through all children and add their information to this node - for (int index = 0; index < 8; index++) - { - if (this.children[index] != null) - { - this.red += this.children[index].red; - this.green += this.children[index].green; - this.blue += this.children[index].blue; - this.alpha += this.children[index].alpha; - this.pixelCount += this.children[index].pixelCount; - ++childNodes; - this.children[index] = null; - } - } - - // Now change this to a leaf node - this.leaf = true; - - // Return the number of nodes to decrement the leaf count by - return childNodes - 1; - } - - /// - /// Traverse the tree, building up the color palette - /// - /// The palette - /// The current palette index - public void ConstructPalette(List palette, ref int index) - { - if (this.leaf) - { - // Consume the next palette index - this.paletteIndex = index++; - - byte r = (this.red / this.pixelCount).ToByte(); - byte g = (this.green / this.pixelCount).ToByte(); - byte b = (this.blue / this.pixelCount).ToByte(); - byte a = (this.alpha / this.pixelCount).ToByte(); - - // And set the color of the palette entry - TColor pixel = default(TColor); - pixel.PackFromVector4(new Color(r, g, b, a).ToVector4()); - palette.Add(pixel); - } - else - { - // Loop through children looking for leaves - for (int i = 0; i < 8; i++) - { - if (this.children[i] != null) - { - this.children[i].ConstructPalette(palette, ref index); - } - } - } - } - - /// - /// Return the palette index for the passed color - /// - /// The representing the pixel. - /// The level. - /// - /// The representing the index of the pixel in the palette. - /// - public int GetPaletteIndex(TColor pixel, int level) - { - int index = this.paletteIndex; - - if (!this.leaf) - { - int shift = 7 - level; - Color color = new Color(pixel.ToVector4()); - int pixelIndex = ((color.A & Mask[0]) >> (shift - 3)) | - ((color.B & Mask[level + 1]) >> (shift - 2)) | - ((color.G & Mask[level + 1]) >> (shift - 1)) | - ((color.R & Mask[level + 1]) >> shift); - - if (this.children[pixelIndex] != null) - { - index = this.children[pixelIndex].GetPaletteIndex(pixel, level + 1); - } - else - { - throw new Exception($"Cannot retrive a pixel at the given index {pixelIndex}."); - } - } - - return index; - } - - /// - /// Increment the pixel count and add to the color information - /// - /// - /// The pixel to add. - /// - public void Increment(TColor pixel) - { - this.pixelCount++; - Color color = new Color(pixel.ToVector4()); - this.red += color.R; - this.green += color.G; - this.blue += color.B; - this.alpha += color.A; - } - } - } - } -} diff --git a/src/ImageSharp46/Quantizers/Octree/Quantizer.cs b/src/ImageSharp46/Quantizers/Octree/Quantizer.cs deleted file mode 100644 index d88832634..000000000 --- a/src/ImageSharp46/Quantizers/Octree/Quantizer.cs +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - using System.Collections.Generic; - using System.Threading.Tasks; - - /// - /// Encapsulates methods to calculate the color palette of an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class Quantizer : IQuantizer - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Flag used to indicate whether a single pass or two passes are needed for quantization. - /// - private readonly bool singlePass; - - /// - /// Initializes a new instance of the class. - /// - /// - /// If true, the quantization only needs to loop through the source pixels once - /// - /// - /// If you construct this class with a true value for singlePass, then the code will, when quantizing your image, - /// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage' - /// and then 'QuantizeImage'. - /// - protected Quantizer(bool singlePass) - { - this.singlePass = singlePass; - } - - /// - public virtual QuantizedImage Quantize(ImageBase image, int maxColors) - { - Guard.NotNull(image, nameof(image)); - - // Get the size of the source image - int height = image.Height; - int width = image.Width; - byte[] quantizedPixels = new byte[width * height]; - List palette; - - using (PixelAccessor pixels = image.Lock()) - { - // Call the FirstPass function if not a single pass algorithm. - // For something like an Octree quantizer, this will run through - // all image pixels, build a data structure, and create a palette. - if (!this.singlePass) - { - this.FirstPass(pixels, width, height); - } - - // Get the palette - palette = this.GetPalette(); - - this.SecondPass(pixels, quantizedPixels, width, height); - } - - return new QuantizedImage(width, height, palette.ToArray(), quantizedPixels); - } - - /// - /// Execute the first pass through the pixels in the image - /// - /// The source data - /// The width in pixels of the image. - /// The height in pixels of the image. - protected virtual void FirstPass(PixelAccessor source, int width, int height) - { - // Loop through each row - for (int y = 0; y < height; y++) - { - // And loop through each column - for (int x = 0; x < width; x++) - { - // Now I have the pixel, call the FirstPassQuantize function... - this.InitialQuantizePixel(source[x, y]); - } - } - } - - /// - /// Execute a second pass through the bitmap - /// - /// The source image. - /// The output pixel array - /// The width in pixels of the image - /// The height in pixels of the image - protected virtual void SecondPass(PixelAccessor source, byte[] output, int width, int height) - { - Parallel.For( - 0, - source.Height, - Bootstrapper.Instance.ParallelOptions, - y => - { - for (int x = 0; x < source.Width; x++) - { - TColor sourcePixel = source[x, y]; - output[(y * source.Width) + x] = this.QuantizePixel(sourcePixel); - } - }); - } - - /// - /// Override this to process the pixel in the first pass of the algorithm - /// - /// The pixel to quantize - /// - /// This function need only be overridden if your quantize algorithm needs two passes, - /// such as an Octree quantizer. - /// - protected virtual void InitialQuantizePixel(TColor pixel) - { - } - - /// - /// Override this to process the pixel in the second pass of the algorithm - /// - /// The pixel to quantize - /// - /// The quantized value - /// - protected abstract byte QuantizePixel(TColor pixel); - - /// - /// Retrieve the palette for the quantized image - /// - /// - /// The new color palette - /// - protected abstract List GetPalette(); - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Quantizers/Options/Quantization.cs b/src/ImageSharp46/Quantizers/Options/Quantization.cs deleted file mode 100644 index 428c8e801..000000000 --- a/src/ImageSharp46/Quantizers/Options/Quantization.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Provides enumeration over how an image should be quantized. - /// - public enum Quantization - { - /// - /// An adaptive Octree quantizer. Fast with good quality. - /// - Octree, - - /// - /// Xiaolin Wu's Color Quantizer which generates high quality output. - /// - Wu, - - /// - /// Palette based, Uses the collection of web-safe colors by default. - /// - Palette - } -} diff --git a/src/ImageSharp46/Quantizers/Palette/PaletteQuantizer.cs b/src/ImageSharp46/Quantizers/Palette/PaletteQuantizer.cs deleted file mode 100644 index 73b7f1af2..000000000 --- a/src/ImageSharp46/Quantizers/Palette/PaletteQuantizer.cs +++ /dev/null @@ -1,130 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.Linq; - - /// - /// Encapsulates methods to create a quantized image based upon the given palette. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class PaletteQuantizer : Quantizer - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// A lookup table for colors - /// - private readonly ConcurrentDictionary colorMap = new ConcurrentDictionary(); - - /// - /// List of all colors in the palette - /// - private TColor[] colors; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The color palette. If none is given this will default to the web safe colors defined - /// in the CSS Color Module Level 4. - /// - public PaletteQuantizer(TColor[] palette = null) - : base(true) - { - if (palette == null) - { - Color[] constants = ColorConstants.WebSafeColors; - List safe = new List { default(TColor) }; - foreach (Color c in constants) - { - TColor packed = default(TColor); - packed.PackFromVector4(c.ToVector4()); - safe.Add(packed); - } - - this.colors = safe.ToArray(); - } - else - { - this.colors = palette; - } - } - - /// - public override QuantizedImage Quantize(ImageBase image, int maxColors) - { - Array.Resize(ref this.colors, maxColors.Clamp(1, 256)); - return base.Quantize(image, maxColors); - } - - /// - protected override byte QuantizePixel(TColor pixel) - { - byte colorIndex = 0; - string colorHash = pixel.ToString(); - - // Check if the color is in the lookup table - if (this.colorMap.ContainsKey(colorHash)) - { - colorIndex = this.colorMap[colorHash]; - } - else - { - // Not found - loop through the palette and find the nearest match. - Color color = new Color(pixel.ToVector4()); - - int leastDistance = int.MaxValue; - int red = color.R; - int green = color.G; - int blue = color.B; - int alpha = color.A; - - for (int index = 0; index < this.colors.Length; index++) - { - Color paletteColor = new Color(this.colors[index].ToVector4()); - int redDistance = paletteColor.R - red; - int greenDistance = paletteColor.G - green; - int blueDistance = paletteColor.B - blue; - int alphaDistance = paletteColor.A - alpha; - - int distance = (redDistance * redDistance) + - (greenDistance * greenDistance) + - (blueDistance * blueDistance) + - (alphaDistance * alphaDistance); - - if (distance < leastDistance) - { - colorIndex = (byte)index; - leastDistance = distance; - - // And if it's an exact match, exit the loop - if (distance == 0) - { - break; - } - } - } - - // Now I have the color, pop it into the cache for next time - this.colorMap.TryAdd(colorHash, colorIndex); - } - - return colorIndex; - } - - /// - protected override List GetPalette() - { - return this.colors.ToList(); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Quantizers/Quantize.cs b/src/ImageSharp46/Quantizers/Quantize.cs deleted file mode 100644 index 0a339a527..000000000 --- a/src/ImageSharp46/Quantizers/Quantize.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using ImageSharp.Quantizers; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies quantization to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The quantization mode to apply to perform the operation. - /// The maximum number of colors to return. Defaults to 256. - /// The . - public static Image Quantize(this Image source, Quantization mode = Quantization.Octree, int maxColors = 256) - where TColor : struct, IPackedPixel - where TPacked : struct - { - IQuantizer quantizer; - switch (mode) - { - case Quantization.Wu: - quantizer = new WuQuantizer(); - break; - - case Quantization.Palette: - quantizer = new PaletteQuantizer(); - break; - - default: - quantizer = new OctreeQuantizer(); - break; - } - - return Quantize(source, quantizer, maxColors); - } - - /// - /// Applies quantization to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The quantizer to apply to perform the operation. - /// The maximum number of colors to return. - /// The . - public static Image Quantize(this Image source, IQuantizer quantizer, int maxColors) - where TColor : struct, IPackedPixel - where TPacked : struct - { - QuantizedImage quantizedImage = quantizer.Quantize(source, maxColors); - source.SetPixels(source.Width, source.Height, quantizedImage.ToImage().Pixels); - return source; - } - } -} diff --git a/src/ImageSharp46/Quantizers/QuantizedImage.cs b/src/ImageSharp46/Quantizers/QuantizedImage.cs deleted file mode 100644 index 956557c62..000000000 --- a/src/ImageSharp46/Quantizers/QuantizedImage.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - using System; - using System.Threading.Tasks; - - /// - /// Represents a quantized image where the pixels indexed by a color palette. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class QuantizedImage - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The image width. - /// The image height. - /// The color palette. - /// The quantized pixels. - public QuantizedImage(int width, int height, TColor[] palette, byte[] pixels) - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(palette, nameof(palette)); - Guard.NotNull(pixels, nameof(pixels)); - - if (pixels.Length != width * height) - { - throw new ArgumentException( - $"Pixel array size must be {nameof(width)} * {nameof(height)}", nameof(pixels)); - } - - this.Width = width; - this.Height = height; - this.Palette = palette; - this.Pixels = pixels; - } - - /// - /// Gets the width of this . - /// - public int Width { get; } - - /// - /// Gets the height of this . - /// - public int Height { get; } - - /// - /// Gets the color palette of this . - /// - public TColor[] Palette { get; } - - /// - /// Gets the pixels of this . - /// - public byte[] Pixels { get; } - - /// - /// Converts this quantized image to a normal image. - /// - /// - /// The - /// - public Image ToImage() - { - Image image = new Image(); - - int pixelCount = this.Pixels.Length; - int palletCount = this.Palette.Length - 1; - TColor[] pixels = new TColor[pixelCount]; - - Parallel.For( - 0, - pixelCount, - Bootstrapper.Instance.ParallelOptions, - i => - { - TColor color = this.Palette[Math.Min(palletCount, this.Pixels[i])]; - pixels[i] = color; - }); - - image.SetPixels(this.Width, this.Height, pixels); - return image; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Quantizers/Wu/Box.cs b/src/ImageSharp46/Quantizers/Wu/Box.cs deleted file mode 100644 index e715c7839..000000000 --- a/src/ImageSharp46/Quantizers/Wu/Box.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - /// - /// Represents a box color cube. - /// - internal sealed class Box - { - /// - /// Gets or sets the min red value, exclusive. - /// - public int R0 { get; set; } - - /// - /// Gets or sets the max red value, inclusive. - /// - public int R1 { get; set; } - - /// - /// Gets or sets the min green value, exclusive. - /// - public int G0 { get; set; } - - /// - /// Gets or sets the max green value, inclusive. - /// - public int G1 { get; set; } - - /// - /// Gets or sets the min blue value, exclusive. - /// - public int B0 { get; set; } - - /// - /// Gets or sets the max blue value, inclusive. - /// - public int B1 { get; set; } - - /// - /// Gets or sets the min alpha value, exclusive. - /// - public int A0 { get; set; } - - /// - /// Gets or sets the max alpha value, inclusive. - /// - public int A1 { get; set; } - - /// - /// Gets or sets the volume. - /// - public int Volume { get; set; } - } -} diff --git a/src/ImageSharp46/Quantizers/Wu/WuQuantizer.cs b/src/ImageSharp46/Quantizers/Wu/WuQuantizer.cs deleted file mode 100644 index 8eabe38e6..000000000 --- a/src/ImageSharp46/Quantizers/Wu/WuQuantizer.cs +++ /dev/null @@ -1,777 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Quantizers -{ - using System; - using System.Collections.Generic; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An implementation of Wu's color quantizer with alpha channel. - /// - /// - /// - /// Based on C Implementation of Xiaolin Wu's Color Quantizer (v. 2) - /// (see Graphics Gems volume II, pages 126-133) - /// (). - /// - /// - /// This adaptation is based on the excellent JeremyAnsel.ColorQuant by Jérémy Ansel - /// - /// - /// - /// Algorithm: Greedy orthogonal bipartition of RGB space for variance - /// minimization aided by inclusion-exclusion tricks. - /// For speed no nearest neighbor search is done. Slightly - /// better performance can be expected by more sophisticated - /// but more expensive versions. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - public sealed class WuQuantizer : IQuantizer - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - - /// - /// The index bits. - /// - private const int IndexBits = 6; - - /// - /// The index alpha bits. - /// - private const int IndexAlphaBits = 3; - - /// - /// The index count. - /// - private const int IndexCount = (1 << IndexBits) + 1; - - /// - /// The index alpha count. - /// - private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1; - - /// - /// The table length. - /// - private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount; - - /// - /// Moment of P(c). - /// - private readonly long[] vwt; - - /// - /// Moment of r*P(c). - /// - private readonly long[] vmr; - - /// - /// Moment of g*P(c). - /// - private readonly long[] vmg; - - /// - /// Moment of b*P(c). - /// - private readonly long[] vmb; - - /// - /// Moment of a*P(c). - /// - private readonly long[] vma; - - /// - /// Moment of c^2*P(c). - /// - private readonly double[] m2; - - /// - /// Color space tag. - /// - private readonly byte[] tag; - - /// - /// Initializes a new instance of the class. - /// - public WuQuantizer() - { - this.vwt = new long[TableLength]; - this.vmr = new long[TableLength]; - this.vmg = new long[TableLength]; - this.vmb = new long[TableLength]; - this.vma = new long[TableLength]; - this.m2 = new double[TableLength]; - this.tag = new byte[TableLength]; - } - - /// - public QuantizedImage Quantize(ImageBase image, int maxColors) - { - Guard.NotNull(image, nameof(image)); - - int colorCount = maxColors.Clamp(1, 256); - - this.Clear(); - - using (PixelAccessor imagePixels = image.Lock()) - { - this.Build3DHistogram(imagePixels); - this.Get3DMoments(); - - Box[] cube; - this.BuildCube(out cube, ref colorCount); - - return this.GenerateResult(imagePixels, colorCount, cube); - } - } - - /// - /// Gets an index. - /// - /// The red value. - /// The green value. - /// The blue value. - /// The alpha value. - /// The index. - private static int GetPaletteIndex(int r, int g, int b, int a) - { - return (r << ((IndexBits * 2) + IndexAlphaBits)) - + (r << (IndexBits + IndexAlphaBits + 1)) - + (g << (IndexBits + IndexAlphaBits)) - + (r << (IndexBits * 2)) - + (r << (IndexBits + 1)) - + (g << IndexBits) - + ((r + g + b) << IndexAlphaBits) - + r + g + b + a; - } - - /// - /// Computes sum over a box of any given statistic. - /// - /// The cube. - /// The moment. - /// The result. - private static double Volume(Box cube, long[] moment) - { - return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - } - - /// - /// Computes part of Volume(cube, moment) that doesn't depend on r1, g1, or b1 (depending on direction). - /// - /// The cube. - /// The direction. - /// The moment. - /// The result. - private static long Bottom(Box cube, int direction, long[] moment) - { - switch (direction) - { - // Red - case 0: - return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - - // Green - case 1: - return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - - // Blue - case 2: - return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - - // Alpha - case 3: - return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - - default: - throw new ArgumentOutOfRangeException(nameof(direction)); - } - } - - /// - /// Computes remainder of Volume(cube, moment), substituting position for r1, g1, or b1 (depending on direction). - /// - /// The cube. - /// The direction. - /// The position. - /// The moment. - /// The result. - private static long Top(Box cube, int direction, int position, long[] moment) - { - switch (direction) - { - // Red - case 0: - return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] - - moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; - - // Green - case 1: - return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; - - // Blue - case 2: - return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; - - // Alpha - case 3: - return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, position)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, position)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, position)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, position)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, position)]; - - default: - throw new ArgumentOutOfRangeException(nameof(direction)); - } - } - - /// - /// Clears the tables. - /// - private void Clear() - { - Array.Clear(this.vwt, 0, TableLength); - Array.Clear(this.vmr, 0, TableLength); - Array.Clear(this.vmg, 0, TableLength); - Array.Clear(this.vmb, 0, TableLength); - Array.Clear(this.vma, 0, TableLength); - Array.Clear(this.m2, 0, TableLength); - - Array.Clear(this.tag, 0, TableLength); - } - - /// - /// Builds a 3-D color histogram of counts, r/g/b, c^2. - /// - /// The pixel accessor. - private void Build3DHistogram(PixelAccessor pixels) - { - for (int y = 0; y < pixels.Height; y++) - { - for (int x = 0; x < pixels.Width; x++) - { - // Colors are expected in r->g->b->a format - Color color = new Color(pixels[x, y].ToVector4()); - - byte r = color.R; - byte g = color.G; - byte b = color.B; - byte a = color.A; - - int inr = r >> (8 - IndexBits); - int ing = g >> (8 - IndexBits); - int inb = b >> (8 - IndexBits); - int ina = a >> (8 - IndexAlphaBits); - - int ind = GetPaletteIndex(inr + 1, ing + 1, inb + 1, ina + 1); - - this.vwt[ind]++; - this.vmr[ind] += r; - this.vmg[ind] += g; - this.vmb[ind] += b; - this.vma[ind] += a; - this.m2[ind] += (r * r) + (g * g) + (b * b) + (a * a); - } - } - } - - /// - /// Converts the histogram into moments so that we can rapidly calculate - /// the sums of the above quantities over any desired box. - /// - private void Get3DMoments() - { - long[] volume = new long[IndexCount * IndexAlphaCount]; - long[] volumeR = new long[IndexCount * IndexAlphaCount]; - long[] volumeG = new long[IndexCount * IndexAlphaCount]; - long[] volumeB = new long[IndexCount * IndexAlphaCount]; - long[] volumeA = new long[IndexCount * IndexAlphaCount]; - double[] volume2 = new double[IndexCount * IndexAlphaCount]; - - long[] area = new long[IndexAlphaCount]; - long[] areaR = new long[IndexAlphaCount]; - long[] areaG = new long[IndexAlphaCount]; - long[] areaB = new long[IndexAlphaCount]; - long[] areaA = new long[IndexAlphaCount]; - double[] area2 = new double[IndexAlphaCount]; - - for (int r = 1; r < IndexCount; r++) - { - Array.Clear(volume, 0, IndexCount * IndexAlphaCount); - Array.Clear(volumeR, 0, IndexCount * IndexAlphaCount); - Array.Clear(volumeG, 0, IndexCount * IndexAlphaCount); - Array.Clear(volumeB, 0, IndexCount * IndexAlphaCount); - Array.Clear(volumeA, 0, IndexCount * IndexAlphaCount); - Array.Clear(volume2, 0, IndexCount * IndexAlphaCount); - - for (int g = 1; g < IndexCount; g++) - { - Array.Clear(area, 0, IndexAlphaCount); - Array.Clear(areaR, 0, IndexAlphaCount); - Array.Clear(areaG, 0, IndexAlphaCount); - Array.Clear(areaB, 0, IndexAlphaCount); - Array.Clear(areaA, 0, IndexAlphaCount); - Array.Clear(area2, 0, IndexAlphaCount); - - for (int b = 1; b < IndexCount; b++) - { - long line = 0; - long lineR = 0; - long lineG = 0; - long lineB = 0; - long lineA = 0; - double line2 = 0; - - for (int a = 1; a < IndexAlphaCount; a++) - { - int ind1 = GetPaletteIndex(r, g, b, a); - - line += this.vwt[ind1]; - lineR += this.vmr[ind1]; - lineG += this.vmg[ind1]; - lineB += this.vmb[ind1]; - lineA += this.vma[ind1]; - line2 += this.m2[ind1]; - - area[a] += line; - areaR[a] += lineR; - areaG[a] += lineG; - areaB[a] += lineB; - areaA[a] += lineA; - area2[a] += line2; - - int inv = (b * IndexAlphaCount) + a; - - volume[inv] += area[a]; - volumeR[inv] += areaR[a]; - volumeG[inv] += areaG[a]; - volumeB[inv] += areaB[a]; - volumeA[inv] += areaA[a]; - volume2[inv] += area2[a]; - - int ind2 = ind1 - GetPaletteIndex(1, 0, 0, 0); - - this.vwt[ind1] = this.vwt[ind2] + volume[inv]; - this.vmr[ind1] = this.vmr[ind2] + volumeR[inv]; - this.vmg[ind1] = this.vmg[ind2] + volumeG[inv]; - this.vmb[ind1] = this.vmb[ind2] + volumeB[inv]; - this.vma[ind1] = this.vma[ind2] + volumeA[inv]; - this.m2[ind1] = this.m2[ind2] + volume2[inv]; - } - } - } - } - } - - /// - /// Computes the weighted variance of a box cube. - /// - /// The cube. - /// The . - private double Variance(Box cube) - { - double dr = Volume(cube, this.vmr); - double dg = Volume(cube, this.vmg); - double db = Volume(cube, this.vmb); - double da = Volume(cube, this.vma); - - double xx = - this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - - return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt)); - } - - /// - /// We want to minimize the sum of the variances of two sub-boxes. - /// The sum(c^2) terms can be ignored since their sum over both sub-boxes - /// is the same (the sum for the whole box) no matter where we split. - /// The remaining terms have a minus sign in the variance formula, - /// so we drop the minus sign and maximize the sum of the two terms. - /// - /// The cube. - /// The direction. - /// The first position. - /// The last position. - /// The cutting point. - /// The whole red. - /// The whole green. - /// The whole blue. - /// The whole alpha. - /// The whole weight. - /// The . - private double Maximize(Box cube, int direction, int first, int last, out int cut, double wholeR, double wholeG, double wholeB, double wholeA, double wholeW) - { - long baseR = Bottom(cube, direction, this.vmr); - long baseG = Bottom(cube, direction, this.vmg); - long baseB = Bottom(cube, direction, this.vmb); - long baseA = Bottom(cube, direction, this.vma); - long baseW = Bottom(cube, direction, this.vwt); - - double max = 0.0; - cut = -1; - - for (int i = first; i < last; i++) - { - double halfR = baseR + Top(cube, direction, i, this.vmr); - double halfG = baseG + Top(cube, direction, i, this.vmg); - double halfB = baseB + Top(cube, direction, i, this.vmb); - double halfA = baseA + Top(cube, direction, i, this.vma); - double halfW = baseW + Top(cube, direction, i, this.vwt); - - double temp; - - if (Math.Abs(halfW) < Epsilon) - { - continue; - } - - temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; - - halfR = wholeR - halfR; - halfG = wholeG - halfG; - halfB = wholeB - halfB; - halfA = wholeA - halfA; - halfW = wholeW - halfW; - - if (Math.Abs(halfW) < Epsilon) - { - continue; - } - - temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; - - if (temp > max) - { - max = temp; - cut = i; - } - } - - return max; - } - - /// - /// Cuts a box. - /// - /// The first set. - /// The second set. - /// Returns a value indicating whether the box has been split. - private bool Cut(Box set1, Box set2) - { - double wholeR = Volume(set1, this.vmr); - double wholeG = Volume(set1, this.vmg); - double wholeB = Volume(set1, this.vmb); - double wholeA = Volume(set1, this.vma); - double wholeW = Volume(set1, this.vwt); - - int cutr; - int cutg; - int cutb; - int cuta; - - double maxr = this.Maximize(set1, 0, set1.R0 + 1, set1.R1, out cutr, wholeR, wholeG, wholeB, wholeA, wholeW); - double maxg = this.Maximize(set1, 1, set1.G0 + 1, set1.G1, out cutg, wholeR, wholeG, wholeB, wholeA, wholeW); - double maxb = this.Maximize(set1, 2, set1.B0 + 1, set1.B1, out cutb, wholeR, wholeG, wholeB, wholeA, wholeW); - double maxa = this.Maximize(set1, 3, set1.A0 + 1, set1.A1, out cuta, wholeR, wholeG, wholeB, wholeA, wholeW); - - int dir; - - if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa)) - { - dir = 0; - - if (cutr < 0) - { - return false; - } - } - else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa)) - { - dir = 1; - } - else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa)) - { - dir = 2; - } - else - { - dir = 3; - } - - set2.R1 = set1.R1; - set2.G1 = set1.G1; - set2.B1 = set1.B1; - set2.A1 = set1.A1; - - switch (dir) - { - // Red - case 0: - set2.R0 = set1.R1 = cutr; - set2.G0 = set1.G0; - set2.B0 = set1.B0; - set2.A0 = set1.A0; - break; - - // Green - case 1: - set2.G0 = set1.G1 = cutg; - set2.R0 = set1.R0; - set2.B0 = set1.B0; - set2.A0 = set1.A0; - break; - - // Blue - case 2: - set2.B0 = set1.B1 = cutb; - set2.R0 = set1.R0; - set2.G0 = set1.G0; - set2.A0 = set1.A0; - break; - - // Alpha - case 3: - set2.A0 = set1.A1 = cuta; - set2.R0 = set1.R0; - set2.G0 = set1.G0; - set2.B0 = set1.B0; - break; - } - - set1.Volume = (set1.R1 - set1.R0) * (set1.G1 - set1.G0) * (set1.B1 - set1.B0) * (set1.A1 - set1.A0); - set2.Volume = (set2.R1 - set2.R0) * (set2.G1 - set2.G0) * (set2.B1 - set2.B0) * (set2.A1 - set2.A0); - - return true; - } - - /// - /// Marks a color space tag. - /// - /// The cube. - /// A label. - private void Mark(Box cube, byte label) - { - for (int r = cube.R0 + 1; r <= cube.R1; r++) - { - for (int g = cube.G0 + 1; g <= cube.G1; g++) - { - for (int b = cube.B0 + 1; b <= cube.B1; b++) - { - for (int a = cube.A0 + 1; a <= cube.A1; a++) - { - this.tag[GetPaletteIndex(r, g, b, a)] = label; - } - } - } - } - } - - /// - /// Builds the cube. - /// - /// The cube. - /// The color count. - private void BuildCube(out Box[] cube, ref int colorCount) - { - cube = new Box[colorCount]; - double[] vv = new double[colorCount]; - - for (int i = 0; i < colorCount; i++) - { - cube[i] = new Box(); - } - - cube[0].R0 = cube[0].G0 = cube[0].B0 = cube[0].A0 = 0; - cube[0].R1 = cube[0].G1 = cube[0].B1 = IndexCount - 1; - cube[0].A1 = IndexAlphaCount - 1; - - int next = 0; - - for (int i = 1; i < colorCount; i++) - { - if (this.Cut(cube[next], cube[i])) - { - vv[next] = cube[next].Volume > 1 ? this.Variance(cube[next]) : 0.0; - vv[i] = cube[i].Volume > 1 ? this.Variance(cube[i]) : 0.0; - } - else - { - vv[next] = 0.0; - i--; - } - - next = 0; - - double temp = vv[0]; - for (int k = 1; k <= i; k++) - { - if (vv[k] > temp) - { - temp = vv[k]; - next = k; - } - } - - if (temp <= 0.0) - { - colorCount = i + 1; - break; - } - } - } - - /// - /// Generates the quantized result. - /// - /// The image pixels. - /// The color count. - /// The cube. - /// The result. - private QuantizedImage GenerateResult(PixelAccessor imagePixels, int colorCount, Box[] cube) - { - List pallette = new List(); - byte[] pixels = new byte[imagePixels.Width * imagePixels.Height]; - int width = imagePixels.Width; - int height = imagePixels.Height; - - for (int k = 0; k < colorCount; k++) - { - this.Mark(cube[k], (byte)k); - - double weight = Volume(cube[k], this.vwt); - - if (Math.Abs(weight) > Epsilon) - { - float r = (float)(Volume(cube[k], this.vmr) / weight); - float g = (float)(Volume(cube[k], this.vmg) / weight); - float b = (float)(Volume(cube[k], this.vmb) / weight); - float a = (float)(Volume(cube[k], this.vma) / weight); - - TColor color = default(TColor); - color.PackFromVector4(new Vector4(r, g, b, a) / 255F); - pallette.Add(color); - } - else - { - pallette.Add(default(TColor)); - } - } - - Parallel.For( - 0, - height, - Bootstrapper.Instance.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - // Expected order r->g->b->a - Color color = new Color(imagePixels[x, y].ToVector4()); - int r = color.R >> (8 - IndexBits); - int g = color.G >> (8 - IndexBits); - int b = color.B >> (8 - IndexBits); - int a = color.A >> (8 - IndexAlphaBits); - - int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); - pixels[(y * width) + x] = this.tag[ind]; - } - }); - - return new QuantizedImage(width, height, pallette.ToArray(), pixels); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/AutoOrient.cs b/src/ImageSharp46/Samplers/AutoOrient.cs deleted file mode 100644 index 6195a2066..000000000 --- a/src/ImageSharp46/Samplers/AutoOrient.cs +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Adjusts an image so that its orientation is suitable for viewing. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to auto rotate. - /// The - public static Image AutoOrient(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Orientation orientation = GetExifOrientation(source); - - switch (orientation) - { - case Orientation.TopRight: - return source.Flip(FlipType.Horizontal); - - case Orientation.BottomRight: - return source.Rotate(RotateType.Rotate180); - - case Orientation.BottomLeft: - return source.Flip(FlipType.Vertical); - - case Orientation.LeftTop: - return source.Rotate(RotateType.Rotate90) - .Flip(FlipType.Horizontal); - - case Orientation.RightTop: - return source.Rotate(RotateType.Rotate90); - - case Orientation.RightBottom: - return source.Flip(FlipType.Vertical) - .Rotate(RotateType.Rotate270); - - case Orientation.LeftBottom: - return source.Rotate(RotateType.Rotate270); - - case Orientation.Unknown: - case Orientation.TopLeft: - default: - return source; - } - } - - /// - /// Returns the current EXIF orientation - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to auto rotate. - /// The - private static Orientation GetExifOrientation(Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (source.ExifProfile == null) - { - return Orientation.Unknown; - } - - ExifValue value = source.ExifProfile.GetValue(ExifTag.Orientation); - if (value == null) - { - return Orientation.Unknown; - } - - Orientation orientation = (Orientation)value.Value; - - source.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft); - - return orientation; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/BoxBlur.cs b/src/ImageSharp46/Samplers/BoxBlur.cs deleted file mode 100644 index 4c0aa8d1f..000000000 --- a/src/ImageSharp46/Samplers/BoxBlur.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a box blur to the image. - /// - /// The pixel format. - /// The packed format. long, float. - /// The image this method extends. - /// The 'radius' value representing the size of the area to sample. - /// The . - public static Image BoxBlur(this Image source, int radius = 7) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return BoxBlur(source, radius, source.Bounds); - } - - /// - /// Applies a box blur to the image. - /// - /// The pixel format. - /// The packed format. long, float. - /// The image this method extends. - /// The 'radius' value representing the size of the area to sample. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image BoxBlur(this Image source, int radius, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new BoxBlurProcessor(radius)); - } - } -} diff --git a/src/ImageSharp46/Samplers/Crop.cs b/src/ImageSharp46/Samplers/Crop.cs deleted file mode 100644 index a266db3b2..000000000 --- a/src/ImageSharp46/Samplers/Crop.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Crops an image to the given width and height. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// The - public static Image Crop(this Image source, int width, int height) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Crop(source, width, height, source.Bounds); - } - - /// - /// Crops an image to the given width and height with the given source rectangle. - /// - /// If the source rectangle is smaller than the target dimensions then the - /// area within the source is resized performing a zoomed crop. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to crop. - /// The target image width. - /// The target image height. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The - public static Image Crop(this Image source, int width, int height, Rectangle sourceRectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - - if (sourceRectangle.Width < width || sourceRectangle.Height < height) - { - // If the source rectangle is smaller than the target perform a - // cropped zoom. - source = source.Resize(sourceRectangle.Width, sourceRectangle.Height); - } - - CropProcessor processor = new CropProcessor(); - return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor); - } - } -} diff --git a/src/ImageSharp46/Samplers/DetectEdges.cs b/src/ImageSharp46/Samplers/DetectEdges.cs deleted file mode 100644 index c28bb3c81..000000000 --- a/src/ImageSharp46/Samplers/DetectEdges.cs +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Detects any edges within the image. Uses the filter - /// operating in Grayscale mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The . - public static Image DetectEdges(this Image source) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return DetectEdges(source, source.Bounds, new SobelProcessor { Grayscale = true }); - } - - /// - /// Detects any edges within the image. Uses the filter - /// operating in Grayscale mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image DetectEdges(this Image source, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return DetectEdges(source, rectangle, new SobelProcessor { Grayscale = true }); - } - - /// - /// Detects any edges within the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The filter for detecting edges. - /// Whether to convert the image to Grayscale first. Defaults to true. - /// The . - public static Image DetectEdges(this Image source, EdgeDetection filter, bool grayscale = true) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return DetectEdges(source, filter, source.Bounds, grayscale); - } - - /// - /// Detects any edges within the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The filter for detecting edges. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// Whether to convert the image to Grayscale first. Defaults to true. - /// The . - public static Image DetectEdges(this Image source, EdgeDetection filter, Rectangle rectangle, bool grayscale = true) - where TColor : struct, IPackedPixel - where TPacked : struct - { - IEdgeDetectorFilter processor; - - switch (filter) - { - case EdgeDetection.Kayyali: - processor = new KayyaliProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.Kirsch: - processor = new KirschProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.Lapacian3X3: - processor = new Laplacian3X3Processor { Grayscale = grayscale }; - break; - - case EdgeDetection.Lapacian5X5: - processor = new Laplacian5X5Processor { Grayscale = grayscale }; - break; - - case EdgeDetection.LaplacianOfGaussian: - processor = new LaplacianOfGaussianProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.Prewitt: - processor = new PrewittProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.RobertsCross: - processor = new RobertsCrossProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.Robinson: - processor = new RobinsonProcessor { Grayscale = grayscale }; - break; - - case EdgeDetection.Scharr: - processor = new ScharrProcessor { Grayscale = grayscale }; - break; - - default: - processor = new SobelProcessor { Grayscale = grayscale }; - break; - } - - return DetectEdges(source, rectangle, processor); - } - - /// - /// Detects any edges within the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The filter for detecting edges. - /// The . - public static Image DetectEdges(this Image source, IEdgeDetectorFilter filter) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return DetectEdges(source, source.Bounds, filter); - } - - /// - /// Detects any edges within the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The filter for detecting edges. - /// The . - public static Image DetectEdges(this Image source, Rectangle rectangle, IEdgeDetectorFilter filter) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, filter); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/EntropyCrop.cs b/src/ImageSharp46/Samplers/EntropyCrop.cs deleted file mode 100644 index 28a2ebf48..000000000 --- a/src/ImageSharp46/Samplers/EntropyCrop.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Crops an image to the area of greatest entropy. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to crop. - /// The threshold for entropic density. - /// The - public static Image EntropyCrop(this Image source, float threshold = .5f) - where TColor : struct, IPackedPixel - where TPacked : struct - { - EntropyCropProcessor processor = new EntropyCropProcessor(threshold); - return source.Process(source.Width, source.Height, source.Bounds, Rectangle.Empty, processor); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Flip.cs b/src/ImageSharp46/Samplers/Flip.cs deleted file mode 100644 index 0e50ad8ac..000000000 --- a/src/ImageSharp46/Samplers/Flip.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Flips an image by the given instructions. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to rotate, flip, or both. - /// The to perform the flip. - /// The - public static Image Flip(this Image source, FlipType flipType) - where TColor : struct, IPackedPixel - where TPacked : struct - { - FlipProcessor processor = new FlipProcessor(flipType); - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/GuassianBlur.cs b/src/ImageSharp46/Samplers/GuassianBlur.cs deleted file mode 100644 index ef09a18f5..000000000 --- a/src/ImageSharp46/Samplers/GuassianBlur.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a Guassian blur to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// The . - public static Image GuassianBlur(this Image source, float sigma = 3f) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return GuassianBlur(source, sigma, source.Bounds); - } - - /// - /// Applies a Guassian blur to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image GuassianBlur(this Image source, float sigma, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new GuassianBlurProcessor(sigma)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/GuassianSharpen.cs b/src/ImageSharp46/Samplers/GuassianSharpen.cs deleted file mode 100644 index 6b433f6ae..000000000 --- a/src/ImageSharp46/Samplers/GuassianSharpen.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a Guassian sharpening filter to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// The . - public static Image GuassianSharpen(this Image source, float sigma = 3f) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return GuassianSharpen(source, sigma, source.Bounds); - } - - /// - /// Applies a Guassian sharpening filter to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image GuassianSharpen(this Image source, float sigma, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Process(rectangle, new GuassianSharpenProcessor(sigma)); - } - } -} diff --git a/src/ImageSharp46/Samplers/OilPainting.cs b/src/ImageSharp46/Samplers/OilPainting.cs deleted file mode 100644 index a938b2325..000000000 --- a/src/ImageSharp46/Samplers/OilPainting.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the colors of the image recreating an oil painting effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The number of intensity levels. Higher values result in a broader range of colour intensities forming part of the result image. - /// The number of neighbouring pixels used in calculating each individual pixel value. - /// The . - public static Image OilPaint(this Image source, int levels = 10, int brushSize = 15) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return OilPaint(source, levels, brushSize, source.Bounds); - } - - /// - /// Alters the colors of the image recreating an oil painting effect. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The number of intensity levels. Higher values result in a broader range of colour intensities forming part of the result image. - /// The number of neighbouring pixels used in calculating each individual pixel value. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image OilPaint(this Image source, int levels, int brushSize, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - Guard.MustBeGreaterThan(levels, 0, nameof(levels)); - - if (brushSize <= 0 || brushSize > source.Height || brushSize > source.Width) - { - throw new ArgumentOutOfRangeException(nameof(brushSize)); - } - - return source.Process(rectangle, new OilPaintingProcessor(levels, brushSize)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Options/AnchorPosition.cs b/src/ImageSharp46/Samplers/Options/AnchorPosition.cs deleted file mode 100644 index c0adb4da4..000000000 --- a/src/ImageSharp46/Samplers/Options/AnchorPosition.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerated anchor positions to apply to resized images. - /// - public enum AnchorPosition - { - /// - /// Anchors the position of the image to the center of it's bounding container. - /// - Center, - - /// - /// Anchors the position of the image to the top of it's bounding container. - /// - Top, - - /// - /// Anchors the position of the image to the bottom of it's bounding container. - /// - Bottom, - - /// - /// Anchors the position of the image to the left of it's bounding container. - /// - Left, - - /// - /// Anchors the position of the image to the right of it's bounding container. - /// - Right, - - /// - /// Anchors the position of the image to the top left side of it's bounding container. - /// - TopLeft, - - /// - /// Anchors the position of the image to the top right side of it's bounding container. - /// - TopRight, - - /// - /// Anchors the position of the image to the bottom right side of it's bounding container. - /// - BottomRight, - - /// - /// Anchors the position of the image to the bottom left side of it's bounding container. - /// - BottomLeft - } -} diff --git a/src/ImageSharp46/Samplers/Options/FlipType.cs b/src/ImageSharp46/Samplers/Options/FlipType.cs deleted file mode 100644 index 5a9668316..000000000 --- a/src/ImageSharp46/Samplers/Options/FlipType.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Provides enumeration over how a image should be flipped. - /// - public enum FlipType - { - /// - /// Don't flip the image. - /// - None, - - /// - /// Flip the image horizontally. - /// - Horizontal, - - /// - /// Flip the image vertically. - /// - Vertical, - } -} diff --git a/src/ImageSharp46/Samplers/Options/Orientation.cs b/src/ImageSharp46/Samplers/Options/Orientation.cs deleted file mode 100644 index dfe57a4b0..000000000 --- a/src/ImageSharp46/Samplers/Options/Orientation.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - internal enum Orientation : ushort - { - Unknown = 0, - TopLeft = 1, - TopRight = 2, - BottomRight = 3, - BottomLeft = 4, - LeftTop = 5, - RightTop = 6, - RightBottom = 7, - LeftBottom = 8 - } -} diff --git a/src/ImageSharp46/Samplers/Options/ResizeHelper.cs b/src/ImageSharp46/Samplers/Options/ResizeHelper.cs deleted file mode 100644 index 33aa32528..000000000 --- a/src/ImageSharp46/Samplers/Options/ResizeHelper.cs +++ /dev/null @@ -1,441 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Linq; - - /// - /// Provides methods to help calculate the target rectangle when resizing using the - /// enumeration. - /// - internal static class ResizeHelper - { - /// - /// Calculates the target location and bounds to perform the resize operation against. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - public static Rectangle CalculateTargetLocationAndBounds(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - switch (options.Mode) - { - case ResizeMode.Crop: - return CalculateCropRectangle(source, options); - case ResizeMode.Pad: - return CalculatePadRectangle(source, options); - case ResizeMode.BoxPad: - return CalculateBoxPadRectangle(source, options); - case ResizeMode.Max: - return CalculateMaxRectangle(source, options); - case ResizeMode.Min: - return CalculateMinRectangle(source, options); - - // Last case ResizeMode.Stretch: - default: - return new Rectangle(0, 0, options.Size.Width, options.Size.Height); - } - } - - /// - /// Calculates the target rectangle for crop mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateCropRectangle(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int width = options.Size.Width; - int height = options.Size.Height; - - if (width <= 0 || height <= 0) - { - return new Rectangle(0, 0, source.Width, source.Height); - } - - double ratio; - int sourceWidth = source.Width; - int sourceHeight = source.Height; - - int destinationX = 0; - int destinationY = 0; - int destinationWidth = width; - int destinationHeight = height; - - // Fractional variants for preserving aspect ratio. - double percentHeight = Math.Abs(height / (double)sourceHeight); - double percentWidth = Math.Abs(width / (double)sourceWidth); - - if (percentHeight < percentWidth) - { - ratio = percentWidth; - - if (options.CenterCoordinates.Any()) - { - double center = -(ratio * sourceHeight) * options.CenterCoordinates.First(); - destinationY = (int)center + (height / 2); - - if (destinationY > 0) - { - destinationY = 0; - } - - if (destinationY < (int)(height - (sourceHeight * ratio))) - { - destinationY = (int)(height - (sourceHeight * ratio)); - } - } - else - { - switch (options.Position) - { - case AnchorPosition.Top: - case AnchorPosition.TopLeft: - case AnchorPosition.TopRight: - destinationY = 0; - break; - case AnchorPosition.Bottom: - case AnchorPosition.BottomLeft: - case AnchorPosition.BottomRight: - destinationY = (int)(height - (sourceHeight * ratio)); - break; - default: - destinationY = (int)((height - (sourceHeight * ratio)) / 2); - break; - } - } - - destinationHeight = (int)Math.Ceiling(sourceHeight * percentWidth); - } - else - { - ratio = percentHeight; - - if (options.CenterCoordinates.Any()) - { - double center = -(ratio * sourceWidth) * options.CenterCoordinates.ToArray()[1]; - destinationX = (int)center + (width / 2); - - if (destinationX > 0) - { - destinationX = 0; - } - - if (destinationX < (int)(width - (sourceWidth * ratio))) - { - destinationX = (int)(width - (sourceWidth * ratio)); - } - } - else - { - switch (options.Position) - { - case AnchorPosition.Left: - case AnchorPosition.TopLeft: - case AnchorPosition.BottomLeft: - destinationX = 0; - break; - case AnchorPosition.Right: - case AnchorPosition.TopRight: - case AnchorPosition.BottomRight: - destinationX = (int)(width - (sourceWidth * ratio)); - break; - default: - destinationX = (int)((width - (sourceWidth * ratio)) / 2); - break; - } - } - - destinationWidth = (int)Math.Ceiling(sourceWidth * percentHeight); - } - - return new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight); - } - - /// - /// Calculates the target rectangle for pad mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculatePadRectangle(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int width = options.Size.Width; - int height = options.Size.Height; - - if (width <= 0 || height <= 0) - { - return new Rectangle(0, 0, source.Width, source.Height); - } - - double ratio; - int sourceWidth = source.Width; - int sourceHeight = source.Height; - - int destinationX = 0; - int destinationY = 0; - int destinationWidth = width; - int destinationHeight = height; - - // Fractional variants for preserving aspect ratio. - double percentHeight = Math.Abs(height / (double)sourceHeight); - double percentWidth = Math.Abs(width / (double)sourceWidth); - - if (percentHeight < percentWidth) - { - ratio = percentHeight; - destinationWidth = Convert.ToInt32(sourceWidth * percentHeight); - - switch (options.Position) - { - case AnchorPosition.Left: - case AnchorPosition.TopLeft: - case AnchorPosition.BottomLeft: - destinationX = 0; - break; - case AnchorPosition.Right: - case AnchorPosition.TopRight: - case AnchorPosition.BottomRight: - destinationX = (int)(width - (sourceWidth * ratio)); - break; - default: - destinationX = Convert.ToInt32((width - (sourceWidth * ratio)) / 2); - break; - } - } - else - { - ratio = percentWidth; - destinationHeight = Convert.ToInt32(sourceHeight * percentWidth); - - switch (options.Position) - { - case AnchorPosition.Top: - case AnchorPosition.TopLeft: - case AnchorPosition.TopRight: - destinationY = 0; - break; - case AnchorPosition.Bottom: - case AnchorPosition.BottomLeft: - case AnchorPosition.BottomRight: - destinationY = (int)(height - (sourceHeight * ratio)); - break; - default: - destinationY = (int)((height - (sourceHeight * ratio)) / 2); - break; - } - } - - return new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight); - } - - /// - /// Calculates the target rectangle for box pad mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateBoxPadRectangle(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int width = options.Size.Width; - int height = options.Size.Height; - - if (width <= 0 || height <= 0) - { - return new Rectangle(0, 0, source.Width, source.Height); - } - - int sourceWidth = source.Width; - int sourceHeight = source.Height; - - // Fractional variants for preserving aspect ratio. - double percentHeight = Math.Abs(height / (double)sourceHeight); - double percentWidth = Math.Abs(width / (double)sourceWidth); - - int boxPadHeight = height > 0 ? height : Convert.ToInt32(sourceHeight * percentWidth); - int boxPadWidth = width > 0 ? width : Convert.ToInt32(sourceWidth * percentHeight); - - // Only calculate if upscaling. - if (sourceWidth < boxPadWidth && sourceHeight < boxPadHeight) - { - int destinationX; - int destinationY; - int destinationWidth = sourceWidth; - int destinationHeight = sourceHeight; - width = boxPadWidth; - height = boxPadHeight; - - switch (options.Position) - { - case AnchorPosition.Left: - destinationY = (height - sourceHeight) / 2; - destinationX = 0; - break; - case AnchorPosition.Right: - destinationY = (height - sourceHeight) / 2; - destinationX = width - sourceWidth; - break; - case AnchorPosition.TopRight: - destinationY = 0; - destinationX = width - sourceWidth; - break; - case AnchorPosition.Top: - destinationY = 0; - destinationX = (width - sourceWidth) / 2; - break; - case AnchorPosition.TopLeft: - destinationY = 0; - destinationX = 0; - break; - case AnchorPosition.BottomRight: - destinationY = height - sourceHeight; - destinationX = width - sourceWidth; - break; - case AnchorPosition.Bottom: - destinationY = height - sourceHeight; - destinationX = (width - sourceWidth) / 2; - break; - case AnchorPosition.BottomLeft: - destinationY = height - sourceHeight; - destinationX = 0; - break; - default: - destinationY = (height - sourceHeight) / 2; - destinationX = (width - sourceWidth) / 2; - break; - } - - return new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight); - } - - // Switch to pad mode to downscale and calculate from there. - return CalculatePadRectangle(source, options); - } - - /// - /// Calculates the target rectangle for max mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateMaxRectangle(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int width = options.Size.Width; - int height = options.Size.Height; - int destinationWidth = width; - int destinationHeight = height; - - // Fractional variants for preserving aspect ratio. - double percentHeight = Math.Abs(height / (double)source.Height); - double percentWidth = Math.Abs(width / (double)source.Width); - - // Integers must be cast to doubles to get needed precision - double ratio = (double)options.Size.Height / options.Size.Width; - double sourceRatio = (double)source.Height / source.Width; - - if (sourceRatio < ratio) - { - destinationHeight = Convert.ToInt32(source.Height * percentWidth); - height = destinationHeight; - } - else - { - destinationWidth = Convert.ToInt32(source.Width * percentHeight); - width = destinationWidth; - } - - // Replace the size to match the rectangle. - options.Size = new Size(width, height); - return new Rectangle(0, 0, destinationWidth, destinationHeight); - } - - /// - /// Calculates the target rectangle for min mode. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateMinRectangle(ImageBase source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - int width = options.Size.Width; - int height = options.Size.Height; - int destinationWidth; - int destinationHeight; - - // Don't upscale - if (width > source.Width || height > source.Height) - { - options.Size = new Size(source.Width, source.Height); - return new Rectangle(0, 0, source.Width, source.Height); - } - - double sourceRatio = (double)source.Height / source.Width; - - // Find the shortest distance to go. - int widthDiff = source.Width - width; - int heightDiff = source.Height - height; - - if (widthDiff < heightDiff) - { - destinationHeight = Convert.ToInt32(width * sourceRatio); - height = destinationHeight; - destinationWidth = width; - } - else if (widthDiff > heightDiff) - { - destinationWidth = Convert.ToInt32(height / sourceRatio); - destinationHeight = height; - width = destinationWidth; - } - else - { - destinationWidth = width; - destinationHeight = height; - } - - // Replace the size to match the rectangle. - options.Size = new Size(width, height); - return new Rectangle(0, 0, destinationWidth, destinationHeight); - } - } -} diff --git a/src/ImageSharp46/Samplers/Options/ResizeMode.cs b/src/ImageSharp46/Samplers/Options/ResizeMode.cs deleted file mode 100644 index 7a1cc3c94..000000000 --- a/src/ImageSharp46/Samplers/Options/ResizeMode.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Enumerated resize modes to apply to resized images. - /// - public enum ResizeMode - { - /// - /// Crops the resized image to fit the bounds of its container. - /// - Crop, - - /// - /// Pads the resized image to fit the bounds of its container. - /// If only one dimension is passed, will maintain the original aspect ratio. - /// - Pad, - - /// - /// Pads the image to fit the bound of the container without resizing the - /// original source. - /// When downscaling, performs the same functionality as - /// - BoxPad, - - /// - /// Constrains the resized image to fit the bounds of its container maintaining - /// the original aspect ratio. - /// - Max, - - /// - /// Resizes the image until the shortest side reaches the set given dimension. - /// Upscaling is disabled in this mode and the original image will be returned - /// if attempted. - /// - Min, - - /// - /// Stretches the resized image to fit the bounds of its container. - /// - Stretch - } -} diff --git a/src/ImageSharp46/Samplers/Options/ResizeOptions.cs b/src/ImageSharp46/Samplers/Options/ResizeOptions.cs deleted file mode 100644 index 3cfb3d6c1..000000000 --- a/src/ImageSharp46/Samplers/Options/ResizeOptions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System.Collections.Generic; - using System.Linq; - - /// - /// The resize options for resizing images against certain modes. - /// - public class ResizeOptions - { - /// - /// Gets or sets the resize mode. - /// - public ResizeMode Mode { get; set; } = ResizeMode.Crop; - - /// - /// Gets or sets the anchor position. - /// - public AnchorPosition Position { get; set; } = AnchorPosition.Center; - - /// - /// Gets or sets the center coordinates. - /// - public IEnumerable CenterCoordinates { get; set; } = Enumerable.Empty(); - - /// - /// Gets or sets the target size. - /// - public Size Size { get; set; } - - /// - /// Gets or sets the sampler to perform the resize operation. - /// - public IResampler Sampler { get; set; } = new BicubicResampler(); - - /// - /// Gets or sets a value indicating whether to compress - /// or expand individual pixel colors the value on processing. - /// - public bool Compand { get; set; } - } -} diff --git a/src/ImageSharp46/Samplers/Options/RotateType.cs b/src/ImageSharp46/Samplers/Options/RotateType.cs deleted file mode 100644 index 0545aa910..000000000 --- a/src/ImageSharp46/Samplers/Options/RotateType.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Provides enumeration over how the image should be rotated. - /// - public enum RotateType - { - /// - /// Do not rotate the image. - /// - None, - - /// - /// Rotate the image by 90 degrees clockwise. - /// - Rotate90 = 90, - - /// - /// Rotate the image by 180 degrees clockwise. - /// - Rotate180 = 180, - - /// - /// Rotate the image by 270 degrees clockwise. - /// - Rotate270 = 270 - } -} diff --git a/src/ImageSharp46/Samplers/Pad.cs b/src/ImageSharp46/Samplers/Pad.cs deleted file mode 100644 index 3c4db20bd..000000000 --- a/src/ImageSharp46/Samplers/Pad.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Evenly pads an image to fit the new dimensions. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The source image to pad. - /// The new width. - /// The new height. - /// The . - public static Image Pad(this Image source, int width, int height) - where TColor : struct, IPackedPixel - where TPacked : struct - { - ResizeOptions options = new ResizeOptions - { - Size = new Size(width, height), - Mode = ResizeMode.BoxPad, - Sampler = new NearestNeighborResampler() - }; - - return Resize(source, options); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Pixelate.cs b/src/ImageSharp46/Samplers/Pixelate.cs deleted file mode 100644 index e7bd84c31..000000000 --- a/src/ImageSharp46/Samplers/Pixelate.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Pixelates an image with the given pixel size. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The size of the pixels. - /// The . - public static Image Pixelate(this Image source, int size = 4) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Pixelate(source, size, source.Bounds); - } - - /// - /// Pixelates an image with the given pixel size. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image this method extends. - /// The size of the pixels. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The . - public static Image Pixelate(this Image source, int size, Rectangle rectangle) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (size <= 0 || size > source.Height || size > source.Width) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - return source.Process(rectangle, new PixelateProcessor(size)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/CompandingResizeProcessor.cs b/src/ImageSharp46/Samplers/Processors/CompandingResizeProcessor.cs deleted file mode 100644 index 2e7a8ec9a..000000000 --- a/src/ImageSharp46/Samplers/Processors/CompandingResizeProcessor.cs +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the resizing of images using various algorithms. - /// This version will expand and compress the image to and from a linear color space during processing. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class CompandingResizeProcessor : ResamplingWeightedProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The sampler to perform the resize operation. - /// - public CompandingResizeProcessor(IResampler sampler) - : base(sampler) - { - } - - /// - public override bool Compand { get; set; } = true; - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - // Jump out, we'll deal with that later. - if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle) - { - return; - } - - int width = target.Width; - int height = target.Height; - int sourceHeight = sourceRectangle.Height; - int targetX = target.Bounds.X; - int targetY = target.Bounds.Y; - int targetRight = target.Bounds.Right; - int targetBottom = target.Bounds.Bottom; - int startX = targetRectangle.X; - int endX = targetRectangle.Right; - - int minX = Math.Max(targetX, startX); - int maxX = Math.Min(targetRight, endX); - int minY = Math.Max(targetY, startY); - int maxY = Math.Min(targetBottom, endY); - - if (this.Sampler is NearestNeighborResampler) - { - // Scaling factors - float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width; - float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Y coordinates of source points - int originY = (int)((y - startY) * heightFactor); - - for (int x = minX; x < maxX; x++) - { - // X coordinates of source points - targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; - } - }); - } - - // Break out now. - return; - } - - // Interpolate the image using the calculated weights. - // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm - // First process the columns. Since we are not using multiple threads startY and endY - // are the upper and lower bounds of the source rectangle. - Image firstPass = new Image(target.Width, source.Height); - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor firstPassPixels = firstPass.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - minX = Math.Max(0, startX); - maxX = Math.Min(width, endX); - minY = Math.Max(0, startY); - maxY = Math.Min(height, endY); - - Parallel.For( - 0, - sourceHeight, - this.ParallelOptions, - y => - { - for (int x = minX; x < maxX; x++) - { - // Ensure offsets are normalised for cropping and padding. - Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values; - - // Destination color components - Vector4 destination = Vector4.Zero; - - for (int i = 0; i < horizontalValues.Length; i++) - { - Weight xw = horizontalValues[i]; - destination += sourcePixels[xw.Index, y].ToVector4().Expand() * xw.Value; - } - - TColor d = default(TColor); - d.PackFromVector4(destination.Compress()); - firstPassPixels[x, y] = d; - } - }); - - // Now process the rows. - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Ensure offsets are normalised for cropping and padding. - Weight[] verticalValues = this.VerticalWeights[y - startY].Values; - - for (int x = 0; x < width; x++) - { - // Destination color components - Vector4 destination = Vector4.Zero; - - for (int i = 0; i < verticalValues.Length; i++) - { - Weight yw = verticalValues[i]; - destination += firstPassPixels[x, yw.Index].ToVector4().Expand() * yw.Value; - } - - TColor d = default(TColor); - d.PackFromVector4(destination.Compress()); - targetPixels[x, y] = d; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/BoxBlurProcessor.cs deleted file mode 100644 index 7b87a3d1b..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/BoxBlurProcessor.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Applies a Box blur filter to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class BoxBlurProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The maximum size of the kernel in either direction. - /// - private readonly int kernelSize; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// - public BoxBlurProcessor(int radius = 7) - { - this.kernelSize = (radius * 2) + 1; - this.KernelX = this.CreateBoxKernel(true); - this.KernelY = this.CreateBoxKernel(false); - } - - /// - /// Gets the horizontal gradient operator. - /// - public float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public float[][] KernelY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - new Convolution2PassFilter(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - } - - /// - /// Create a 1 dimensional Box kernel. - /// - /// Whether to calculate a horizontal kernel. - /// The - private float[][] CreateBoxKernel(bool horizontal) - { - int size = this.kernelSize; - float[][] kernel = horizontal ? new float[1][] : new float[size][]; - - if (horizontal) - { - kernel[0] = new float[size]; - } - - float sum = 0.0f; - - for (int i = 0; i < size; i++) - { - float x = 1; - sum += x; - if (horizontal) - { - kernel[0][i] = x; - } - else - { - kernel[i] = new[] { x }; - } - } - - // Normalise kernel so that the sum of all weights equals 1 - if (horizontal) - { - for (int i = 0; i < size; i++) - { - kernel[0][i] = kernel[0][i] / sum; - } - } - else - { - for (int i = 0; i < size; i++) - { - kernel[i][0] = kernel[i][0] / sum; - } - } - - return kernel; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2DFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2DFilter.cs deleted file mode 100644 index 1b77e41eb..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2DFilter.cs +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Defines a filter that uses two one-dimensional matrices to perform convolution against an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class Convolution2DFilter : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The horizontal gradient operator. - /// The vertical gradient operator. - public Convolution2DFilter(float[][] kernelX, float[][] kernelY) - { - this.KernelX = kernelX; - this.KernelY = kernelY; - } - - /// - /// Gets the horizontal gradient operator. - /// - public float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public float[][] KernelY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int kernelYHeight = this.KernelY.Length; - int kernelYWidth = this.KernelY[0].Length; - int kernelXHeight = this.KernelX.Length; - int kernelXWidth = this.KernelX[0].Length; - int radiusY = kernelYHeight >> 1; - int radiusX = kernelXWidth >> 1; - - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int maxY = sourceBottom - 1; - int maxX = endX - 1; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - this.ParallelOptions, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - float rX = 0; - float gX = 0; - float bX = 0; - float rY = 0; - float gY = 0; - float bY = 0; - - // Apply each matrix multiplier to the color components for each pixel. - for (int fy = 0; fy < kernelYHeight; fy++) - { - int fyr = fy - radiusY; - int offsetY = y + fyr; - - offsetY = offsetY.Clamp(0, maxY); - - for (int fx = 0; fx < kernelXWidth; fx++) - { - int fxr = fx - radiusX; - int offsetX = x + fxr; - - offsetX = offsetX.Clamp(0, maxX); - - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); - float r = currentColor.X; - float g = currentColor.Y; - float b = currentColor.Z; - - if (fy < kernelXHeight) - { - rX += this.KernelX[fy][fx] * r; - gX += this.KernelX[fy][fx] * g; - bX += this.KernelX[fy][fx] * b; - } - - if (fx < kernelYWidth) - { - rY += this.KernelY[fy][fx] * r; - gY += this.KernelY[fy][fx] * g; - bY += this.KernelY[fy][fx] * b; - } - } - } - - float red = (float)Math.Sqrt((rX * rX) + (rY * rY)); - float green = (float)Math.Sqrt((gX * gX) + (gY * gY)); - float blue = (float)Math.Sqrt((bX * bX) + (bY * bY)); - - Vector4 targetColor = targetPixels[x, y].ToVector4(); - TColor packed = default(TColor); - packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z)); - targetPixels[x, y] = packed; - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2PassFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2PassFilter.cs deleted file mode 100644 index 4cab6f0b2..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/Convolution2PassFilter.cs +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Defines a filter that uses two one-dimensional matrices to perform two-pass convolution against an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class Convolution2PassFilter : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The horizontal gradient operator. - /// The vertical gradient operator. - public Convolution2PassFilter(float[][] kernelX, float[][] kernelY) - { - this.KernelX = kernelX; - this.KernelY = kernelY; - } - - /// - /// Gets the horizontal gradient operator. - /// - public float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public float[][] KernelY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float[][] kernelX = this.KernelX; - float[][] kernelY = this.KernelY; - - ImageBase firstPass = new Image(source.Width, source.Height); - this.ApplyConvolution(firstPass, source, sourceRectangle, startY, endY, kernelX); - this.ApplyConvolution(target, firstPass, sourceRectangle, startY, endY, kernelY); - } - - /// - /// Applies the process to the specified portion of the specified at the specified location - /// and with the specified size. - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The index of the row within the source image to start processing. - /// The index of the row within the source image to end processing. - /// The kernel operator. - private void ApplyConvolution(ImageBase target, ImageBase source, Rectangle sourceRectangle, int startY, int endY, float[][] kernel) - { - int kernelHeight = kernel.Length; - int kernelWidth = kernel[0].Length; - int radiusY = kernelHeight >> 1; - int radiusX = kernelWidth >> 1; - - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int maxY = sourceBottom - 1; - int maxX = endX - 1; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - this.ParallelOptions, - y => - { - for (int x = startX; x < endX; x++) - { - Vector4 destination = default(Vector4); - - // Apply each matrix multiplier to the color components for each pixel. - for (int fy = 0; fy < kernelHeight; fy++) - { - int fyr = fy - radiusY; - int offsetY = y + fyr; - - offsetY = offsetY.Clamp(0, maxY); - - for (int fx = 0; fx < kernelWidth; fx++) - { - int fxr = fx - radiusX; - int offsetX = x + fxr; - - offsetX = offsetX.Clamp(0, maxX); - - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); - destination += kernel[fy][fx] * currentColor; - } - } - - TColor packed = default(TColor); - packed.PackFromVector4(destination); - targetPixels[x, y] = packed; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/ConvolutionFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/ConvolutionFilter.cs deleted file mode 100644 index c94bee764..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/ConvolutionFilter.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Defines a filter that uses a 2 dimensional matrix to perform convolution against an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class ConvolutionFilter : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The 2d gradient operator. - public ConvolutionFilter(float[][] kernelXY) - { - this.KernelXY = kernelXY; - } - - /// - /// Gets the 2d gradient operator. - /// - public virtual float[][] KernelXY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float[][] kernelX = this.KernelXY; - int kernelLength = kernelX.GetLength(0); - int radius = kernelLength >> 1; - - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int maxY = sourceBottom - 1; - int maxX = endX - 1; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - this.ParallelOptions, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - float rX = 0; - float gX = 0; - float bX = 0; - - // Apply each matrix multiplier to the color components for each pixel. - for (int fy = 0; fy < kernelLength; fy++) - { - int fyr = fy - radius; - int offsetY = y + fyr; - - offsetY = offsetY.Clamp(0, maxY); - - for (int fx = 0; fx < kernelLength; fx++) - { - int fxr = fx - radius; - int offsetX = x + fxr; - - offsetX = offsetX.Clamp(0, maxX); - - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); - float r = currentColor.X; - float g = currentColor.Y; - float b = currentColor.Z; - - rX += kernelX[fy][fx] * r; - gX += kernelX[fy][fx] * g; - bX += kernelX[fy][fx] * b; - } - } - - float red = rX; - float green = gX; - float blue = bX; - - Vector4 targetColor = targetPixels[x, y].ToVector4(); - TColor packed = default(TColor); - packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z)); - targetPixels[x, y] = packed; - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs deleted file mode 100644 index a689415f6..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Defines a filter that detects edges within an image using two - /// one-dimensional matrices. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class EdgeDetector2DFilter : ImageSampler, IEdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Gets the horizontal gradient operator. - /// - public abstract float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public abstract float[][] KernelY { get; } - - /// - public bool Grayscale { get; set; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - // TODO: Figure out a way to pass event handlers to child classes. - new Convolution2DFilter(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.Grayscale) - { - new GrayscaleBt709Processor().Apply(source, sourceRectangle); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs deleted file mode 100644 index 6d5053111..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Defines a filter that detects edges within an image using a eight two dimensional matrices. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class EdgeDetectorCompassFilter : ImageSampler, IEdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Gets the North gradient operator - /// - public abstract float[][] North { get; } - - /// - /// Gets the NorthWest gradient operator - /// - public abstract float[][] NorthWest { get; } - - /// - /// Gets the West gradient operator - /// - public abstract float[][] West { get; } - - /// - /// Gets the SouthWest gradient operator - /// - public abstract float[][] SouthWest { get; } - - /// - /// Gets the South gradient operator - /// - public abstract float[][] South { get; } - - /// - /// Gets the SouthEast gradient operator - /// - public abstract float[][] SouthEast { get; } - - /// - /// Gets the East gradient operator - /// - public abstract float[][] East { get; } - - /// - /// Gets the NorthEast gradient operator - /// - public abstract float[][] NorthEast { get; } - - /// - public bool Grayscale { get; set; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float[][][] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast }; - - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // First run. - new ConvolutionFilter(kernels[0]).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - - if (kernels.Length == 1) - { - return; - } - - int shiftY = startY; - int shiftX = startX; - - // Reset offset if necessary. - if (minX > 0) - { - shiftX = 0; - } - - if (minY > 0) - { - shiftY = 0; - } - - // Additional runs. - for (int i = 1; i < kernels.Length; i++) - { - ImageBase pass = new Image(source.Width, source.Height); - new ConvolutionFilter(kernels[i]).Apply(pass, source, sourceRectangle, targetRectangle, startY, endY); - - using (PixelAccessor passPixels = pass.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - shiftY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - shiftX; - - // Grab the max components of the two pixels - TColor packed = default(TColor); - packed.PackFromVector4(Vector4.Max(passPixels[offsetX, offsetY].ToVector4(), targetPixels[offsetX, offsetY].ToVector4())); - targetPixels[offsetX, offsetY] = packed; - } - }); - } - } - } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.Grayscale) - { - new GrayscaleBt709Processor().Apply(source, sourceRectangle); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs deleted file mode 100644 index a565dbfc1..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Defines a filter that detects edges within an image using a single two dimensional matrix. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class EdgeDetectorFilter : ImageSampler, IEdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public bool Grayscale { get; set; } - - /// - /// Gets the 2d gradient operator. - /// - public abstract float[][] KernelXY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - new ConvolutionFilter(this.KernelXY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.Grayscale) - { - new GrayscaleBt709Processor().Apply(source, sourceRectangle); - } - } - } -} diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs deleted file mode 100644 index 700201ea4..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Provides properties and methods allowing the detection of edges within an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IEdgeDetectorFilter : IImageSampler, IEdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - } - - /// - /// Provides properties and methods allowing the detection of edges within an image. - /// - public interface IEdgeDetectorFilter - { - /// - /// Gets or sets a value indicating whether to convert the image to grayscale before performing edge detection. - /// - bool Grayscale { get; set; } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs deleted file mode 100644 index cbe45f8b6..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Kayyali operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class KayyaliProcessor : EdgeDetector2DFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The horizontal gradient operator. - /// - private static readonly float[][] KayyaliX = - { - new float[] { 6, 0, -6 }, - new float[] { 0, 0, 0 }, - new float[] { -6, 0, 6 } - }; - - /// - /// The vertical gradient operator. - /// - private static readonly float[][] KayyaliY = - { - new float[] { -6, 0, 6 }, - new float[] { 0, 0, 0 }, - new float[] { 6, 0, -6 } - }; - - /// - public override float[][] KernelX => KayyaliX; - - /// - public override float[][] KernelY => KayyaliY; - } -} diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs deleted file mode 100644 index b8ead4192..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Kirsch operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class KirschProcessor : EdgeDetectorCompassFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The North gradient operator - /// - private static readonly float[][] KirschNorth = - { - new float[] { 5, 5, 5 }, - new float[] { -3, 0, -3 }, - new float[] { -3, -3, -3 } - }; - - /// - /// The NorthWest gradient operator - /// - private static readonly float[][] KirschNorthWest = - { - new float[] { 5, 5, -3 }, - new float[] { 5, 0, -3 }, - new float[] { -3, -3, -3 } - }; - - /// - /// The West gradient operator - /// - private static readonly float[][] KirschWest = - { - new float[] { 5, -3, -3 }, - new float[] { 5, 0, -3 }, - new float[] { 5, -3, -3 } - }; - - /// - /// The SouthWest gradient operator - /// - private static readonly float[][] KirschSouthWest = - { - new float[] { -3, -3, -3 }, - new float[] { 5, 0, -3 }, - new float[] { 5, 5, -3 } - }; - - /// - /// The South gradient operator - /// - private static readonly float[][] KirschSouth = - { - new float[] { -3, -3, -3 }, - new float[] { -3, 0, -3 }, - new float[] { 5, 5, 5 } - }; - - /// - /// The SouthEast gradient operator - /// - private static readonly float[][] KirschSouthEast = - { - new float[] { -3, -3, -3 }, - new float[] { -3, 0, 5 }, - new float[] { -3, 5, 5 } - }; - - /// - /// The East gradient operator - /// - private static readonly float[][] KirschEast = - { - new float[] { -3, -3, 5 }, - new float[] { -3, 0, 5 }, - new float[] { -3, -3, 5 } - }; - - /// - /// The NorthEast gradient operator - /// - private static readonly float[][] KirschNorthEast = - { - new float[] { -3, 5, 5 }, - new float[] { -3, 0, 5 }, - new float[] { -3, -3, -3 } - }; - - /// - public override float[][] North => KirschNorth; - - /// - public override float[][] NorthWest => KirschNorthWest; - - /// - public override float[][] West => KirschWest; - - /// - public override float[][] SouthWest => KirschSouthWest; - - /// - public override float[][] South => KirschSouth; - - /// - public override float[][] SouthEast => KirschSouthEast; - - /// - public override float[][] East => KirschEast; - - /// - public override float[][] NorthEast => KirschNorthEast; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs deleted file mode 100644 index 9fbf71674..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Laplacian 3 x 3 operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class Laplacian3X3Processor : EdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The 2d gradient operator. - /// - private static readonly float[][] Laplacian3X3XY = new float[][] - { - new float[] { -1, -1, -1 }, - new float[] { -1, 8, -1 }, - new float[] { -1, -1, -1 } - }; - - /// - public override float[][] KernelXY => Laplacian3X3XY; - } -} diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs deleted file mode 100644 index fdff0ec3a..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Laplacian 5 x 5 operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class Laplacian5X5Processor : EdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The 2d gradient operator. - /// - private static readonly float[][] Laplacian5X5XY = - { - new float[] { -1, -1, -1, -1, -1 }, - new float[] { -1, -1, -1, -1, -1 }, - new float[] { -1, -1, 24, -1, -1 }, - new float[] { -1, -1, -1, -1, -1 }, - new float[] { -1, -1, -1, -1, -1 } - }; - - /// - public override float[][] KernelXY => Laplacian5X5XY; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs deleted file mode 100644 index 75e0efbd2..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Laplacian of Gaussian operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class LaplacianOfGaussianProcessor : EdgeDetectorFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The 2d gradient operator. - /// - private static readonly float[][] LaplacianOfGaussianXY = - { - new float[] { 0, 0, -1, 0, 0 }, - new float[] { 0, -1, -2, -1, 0 }, - new float[] { -1, -2, 16, -2, -1 }, - new float[] { 0, -1, -2, -1, 0 }, - new float[] { 0, 0, -1, 0, 0 } - }; - - /// - public override float[][] KernelXY => LaplacianOfGaussianXY; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs deleted file mode 100644 index 70b763e63..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Prewitt operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class PrewittProcessor : EdgeDetector2DFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The horizontal gradient operator. - /// - private static readonly float[][] PrewittX = - { - new float[] { -1, 0, 1 }, - new float[] { -1, 0, 1 }, - new float[] { -1, 0, 1 } - }; - - /// - /// The vertical gradient operator. - /// - private static readonly float[][] PrewittY = - { - new float[] { 1, 1, 1 }, - new float[] { 0, 0, 0 }, - new float[] { -1, -1, -1 } - }; - - /// - public override float[][] KernelX => PrewittX; - - /// - public override float[][] KernelY => PrewittY; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs deleted file mode 100644 index 8eb3aac3b..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Roberts Cross operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class RobertsCrossProcessor : EdgeDetector2DFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The horizontal gradient operator. - /// - private static readonly float[][] RobertsCrossX = - { - new float[] { 1, 0 }, - new float[] { 0, -1 } - }; - - /// - /// The vertical gradient operator. - /// - private static readonly float[][] RobertsCrossY = - { - new float[] { 0, 1 }, - new float[] { -1, 0 } - }; - - /// - public override float[][] KernelX => RobertsCrossX; - - /// - public override float[][] KernelY => RobertsCrossY; - } -} diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs deleted file mode 100644 index 189215f08..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Kirsch operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class RobinsonProcessor : EdgeDetectorCompassFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The North gradient operator - /// - private static readonly float[][] RobinsonNorth = - { - new float[] { 1, 2, 1 }, - new float[] { 0, 0, 0 }, - new float[] { -1, -2, -1 } - }; - - /// - /// The NorthWest gradient operator - /// - private static readonly float[][] RobinsonNorthWest = - { - new float[] { 2, 1, 0 }, - new float[] { 1, 0, -1 }, - new float[] { 0, -1, -2 } - }; - - /// - /// The West gradient operator - /// - private static readonly float[][] RobinsonWest = - { - new float[] { 1, 0, -1 }, - new float[] { 2, 0, -2 }, - new float[] { 1, 0, -1 } - }; - - /// - /// The SouthWest gradient operator - /// - private static readonly float[][] RobinsonSouthWest = - { - new float[] { 0, -1, -2 }, - new float[] { 1, 0, -1 }, - new float[] { 2, 1, 0 } - }; - - /// - /// The South gradient operator - /// - private static readonly float[][] RobinsonSouth = - { - new float[] { -1, -2, -1 }, - new float[] { 0, 0, 0 }, - new float[] { 1, 2, 1 } - }; - - /// - /// The SouthEast gradient operator - /// - private static readonly float[][] RobinsonSouthEast = - { - new float[] { -2, -1, 0 }, - new float[] { -1, 0, 1 }, - new float[] { 0, 1, 2 } - }; - - /// - /// The East gradient operator - /// - private static readonly float[][] RobinsonEast = - { - new float[] { -1, 0, 1 }, - new float[] { -2, 0, 2 }, - new float[] { -1, 0, 1 } - }; - - /// - /// The NorthEast gradient operator - /// - private static readonly float[][] RobinsonNorthEast = - { - new float[] { 0, 1, 2 }, - new float[] { -1, 0, 1 }, - new float[] { -2, -1, 0 } - }; - - /// - public override float[][] North => RobinsonNorth; - - /// - public override float[][] NorthWest => RobinsonNorthWest; - - /// - public override float[][] West => RobinsonWest; - - /// - public override float[][] SouthWest => RobinsonSouthWest; - - /// - public override float[][] South => RobinsonSouth; - - /// - public override float[][] SouthEast => RobinsonSouthEast; - - /// - public override float[][] East => RobinsonEast; - - /// - public override float[][] NorthEast => RobinsonNorthEast; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs deleted file mode 100644 index 22e7d8084..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Scharr operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class ScharrProcessor : EdgeDetector2DFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The horizontal gradient operator. - /// - private static readonly float[][] ScharrX = new float[3][] - { - new float[] { -3, 0, 3 }, - new float[] { -10, 0, 10 }, - new float[] { -3, 0, 3 } - }; - - /// - /// The vertical gradient operator. - /// - private static readonly float[][] ScharrY = new float[3][] - { - new float[] { 3, 10, 3 }, - new float[] { 0, 0, 0 }, - new float[] { -3, -10, -3 } - }; - - /// - public override float[][] KernelX => ScharrX; - - /// - public override float[][] KernelY => ScharrY; - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs deleted file mode 100644 index 7d9521c69..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Diagnostics.CodeAnalysis; - - /// - /// The Sobel operator filter. - /// - /// - /// The pixel format. - /// The packed format. uint, long, float. - [SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")] - public class SobelProcessor : EdgeDetector2DFilter - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The horizontal gradient operator. - /// - private static readonly float[][] SobelX = - { - new float[] { -1, 0, 1 }, - new float[] { -2, 0, 2 }, - new float[] { -1, 0, 1 } - }; - - /// - /// The vertical gradient operator. - /// - private static readonly float[][] SobelY = - { - new float[] { -1, -2, -1 }, - new float[] { 0, 0, 0 }, - new float[] { 1, 2, 1 } - }; - - /// - public override float[][] KernelX => SobelX; - - /// - public override float[][] KernelY => SobelY; - } -} diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/GuassianBlurProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/GuassianBlurProcessor.cs deleted file mode 100644 index 856239385..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/GuassianBlurProcessor.cs +++ /dev/null @@ -1,142 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - - /// - /// Applies a Gaussian blur filter to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class GuassianBlurProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The maximum size of the kernel in either direction. - /// - private readonly int kernelSize; - - /// - /// The spread of the blur. - /// - private readonly float sigma; - - /// - /// Initializes a new instance of the class. - /// - /// The 'sigma' value representing the weight of the blur. - public GuassianBlurProcessor(float sigma = 3f) - { - this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1; - this.sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// - public GuassianBlurProcessor(int radius) - { - this.kernelSize = (radius * 2) + 1; - this.sigma = radius; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'sigma' value representing the weight of the blur. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// This should be at least twice the sigma value. - /// - public GuassianBlurProcessor(float sigma, int radius) - { - this.kernelSize = (radius * 2) + 1; - this.sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Gets the horizontal gradient operator. - /// - public float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public float[][] KernelY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - new Convolution2PassFilter(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - } - - /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function - /// - /// Whether to calculate a horizontal kernel. - /// The - private float[][] CreateGaussianKernel(bool horizontal) - { - int size = this.kernelSize; - float weight = this.sigma; - float[][] kernel = horizontal ? new float[1][] : new float[size][]; - - if (horizontal) - { - kernel[0] = new float[size]; - } - - float sum = 0.0f; - - float midpoint = (size - 1) / 2f; - for (int i = 0; i < size; i++) - { - float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); - sum += gx; - if (horizontal) - { - kernel[0][i] = gx; - } - else - { - kernel[i] = new[] { gx }; - } - } - - // Normalise kernel so that the sum of all weights equals 1 - if (horizontal) - { - for (int i = 0; i < size; i++) - { - kernel[0][i] = kernel[0][i] / sum; - } - } - else - { - for (int i = 0; i < size; i++) - { - kernel[i][0] = kernel[i][0] / sum; - } - } - - return kernel; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Convolution/GuassianSharpenProcessor.cs b/src/ImageSharp46/Samplers/Processors/Convolution/GuassianSharpenProcessor.cs deleted file mode 100644 index 3c86fcfee..000000000 --- a/src/ImageSharp46/Samplers/Processors/Convolution/GuassianSharpenProcessor.cs +++ /dev/null @@ -1,180 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - - /// - /// Applies a Gaussian sharpening filter to the image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class GuassianSharpenProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The maximum size of the kernel in either direction. - /// - private readonly int kernelSize; - - /// - /// The spread of the blur. - /// - private readonly float sigma; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'sigma' value representing the weight of the sharpening. - /// - public GuassianSharpenProcessor(float sigma = 3f) - { - this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1; - this.sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// - public GuassianSharpenProcessor(int radius) - { - this.kernelSize = (radius * 2) + 1; - this.sigma = radius; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'sigma' value representing the weight of the sharpen. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// This should be at least twice the sigma value. - /// - public GuassianSharpenProcessor(float sigma, int radius) - { - this.kernelSize = (radius * 2) + 1; - this.sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); - } - - /// - /// Gets the horizontal gradient operator. - /// - public float[][] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public float[][] KernelY { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - new Convolution2PassFilter(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY); - } - - /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function - /// - /// Whether to calculate a horizontal kernel. - /// The - private float[][] CreateGaussianKernel(bool horizontal) - { - int size = this.kernelSize; - float weight = this.sigma; - float[][] kernel = horizontal ? new float[1][] : new float[size][]; - - if (horizontal) - { - kernel[0] = new float[size]; - } - - float sum = 0; - - float midpoint = (size - 1) / 2f; - for (int i = 0; i < size; i++) - { - float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); - sum += gx; - if (horizontal) - { - kernel[0][i] = gx; - } - else - { - kernel[i] = new[] { gx }; - } - } - - // Invert the kernel for sharpening. - int midpointRounded = (int)midpoint; - - if (horizontal) - { - for (int i = 0; i < size; i++) - { - if (i == midpointRounded) - { - // Calculate central value - kernel[0][i] = (2f * sum) - kernel[0][i]; - } - else - { - // invert value - kernel[0][i] = -kernel[0][i]; - } - } - } - else - { - for (int i = 0; i < size; i++) - { - if (i == midpointRounded) - { - // Calculate central value - kernel[i][0] = (2 * sum) - kernel[i][0]; - } - else - { - // invert value - kernel[i][0] = -kernel[i][0]; - } - } - } - - // Normalise kernel so that the sum of all weights equals 1 - if (horizontal) - { - for (int i = 0; i < size; i++) - { - kernel[0][i] = kernel[0][i] / sum; - } - } - else - { - for (int i = 0; i < size; i++) - { - kernel[i][0] = kernel[i][0] / sum; - } - } - - return kernel; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/CropProcessor.cs b/src/ImageSharp46/Samplers/Processors/CropProcessor.cs deleted file mode 100644 index 0e8510837..000000000 --- a/src/ImageSharp46/Samplers/Processors/CropProcessor.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Threading.Tasks; - - /// - /// Provides methods to allow the cropping of an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class CropProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = targetRectangle.X; - int endX = targetRectangle.Right; - int sourceX = sourceRectangle.X; - int sourceY = sourceRectangle.Y; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - this.ParallelOptions, - y => - { - for (int x = startX; x < endX; x++) - { - targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY]; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/EntropyCropProcessor.cs b/src/ImageSharp46/Samplers/Processors/EntropyCropProcessor.cs deleted file mode 100644 index dbb99d1c4..000000000 --- a/src/ImageSharp46/Samplers/Processors/EntropyCropProcessor.cs +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Provides methods to allow the cropping of an image to preserve areas of highest - /// entropy. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class EntropyCropProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The rectangle for cropping - /// - private Rectangle cropRectangle; - - /// - /// Initializes a new instance of the class. - /// - /// The threshold to split the image. Must be between 0 and 1. - /// - /// is less than 0 or is greater than 1. - /// - public EntropyCropProcessor(float threshold) - { - Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); - this.Value = threshold; - } - - /// - /// Gets the threshold value. - /// - public float Value { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - // Jump out, we'll deal with that later. - if (source.Bounds == target.Bounds) - { - return; - } - - int targetY = this.cropRectangle.Y; - int targetBottom = this.cropRectangle.Bottom; - int startX = this.cropRectangle.X; - int endX = this.cropRectangle.Right; - - int minY = Math.Max(targetY, startY); - int maxY = Math.Min(targetBottom, endY); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - for (int x = startX; x < endX; x++) - { - targetPixels[x - startX, y - targetY] = sourcePixels[x, y]; - } - }); - } - } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - ImageBase temp = new Image(source.Width, source.Height); - - // Detect the edges. - new SobelProcessor().Apply(temp, source, sourceRectangle); - - // Apply threshold binarization filter. - new BinaryThresholdProcessor(.5f).Apply(temp, sourceRectangle); - - // Search for the first white pixels - Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); - - // Reset the target pixel to the correct size. - target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]); - this.cropRectangle = rectangle; - } - - /// - protected override void AfterApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - // Copy the pixels over. - if (source.Bounds == target.Bounds) - { - target.ClonePixels(target.Width, target.Height, source.Pixels); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/FlipProcessor.cs b/src/ImageSharp46/Samplers/Processors/FlipProcessor.cs deleted file mode 100644 index d6efccec7..000000000 --- a/src/ImageSharp46/Samplers/Processors/FlipProcessor.cs +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the flipping of an image around its center point. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class FlipProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The used to perform flipping. - public FlipProcessor(FlipType flipType) - { - this.FlipType = flipType; - } - - /// - /// Gets the used to perform flipping. - /// - public FlipType FlipType { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - target.ClonePixels(target.Width, target.Height, source.Pixels); - - switch (this.FlipType) - { - // No default needed as we have already set the pixels. - case FlipType.Vertical: - this.FlipX(target); - break; - case FlipType.Horizontal: - this.FlipY(target); - break; - } - } - - /// - /// Swaps the image at the X-axis, which goes horizontally through the middle - /// at half the height of the image. - /// - /// Target image to apply the process to. - private void FlipX(ImageBase target) - { - int width = target.Width; - int height = target.Height; - int halfHeight = (int)Math.Ceiling(target.Height * .5F); - Image temp = new Image(width, height); - temp.ClonePixels(width, height, target.Pixels); - - using (PixelAccessor targetPixels = target.Lock()) - using (PixelAccessor tempPixels = temp.Lock()) - { - Parallel.For( - 0, - halfHeight, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - int newY = height - y - 1; - targetPixels[x, y] = tempPixels[x, newY]; - targetPixels[x, newY] = tempPixels[x, y]; - } - }); - } - } - - /// - /// Swaps the image at the Y-axis, which goes vertically through the middle - /// at half of the width of the image. - /// - /// Target image to apply the process to. - private void FlipY(ImageBase target) - { - int width = target.Width; - int height = target.Height; - int halfWidth = (int)Math.Ceiling(width * .5F); - Image temp = new Image(width, height); - temp.ClonePixels(width, height, target.Pixels); - - using (PixelAccessor targetPixels = target.Lock()) - using (PixelAccessor tempPixels = temp.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < halfWidth; x++) - { - int newX = width - x - 1; - targetPixels[x, y] = tempPixels[newX, y]; - targetPixels[newX, y] = tempPixels[x, y]; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/IImageSampler.cs b/src/ImageSharp46/Samplers/Processors/IImageSampler.cs deleted file mode 100644 index 891a810d1..000000000 --- a/src/ImageSharp46/Samplers/Processors/IImageSampler.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// Encapsulates methods to alter the pixels of an image. The processor creates a copy of the original image to operate on. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public interface IImageSampler : IImageProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Applies the process to the specified portion of the specified . - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// The method keeps the source image unchanged and returns the - /// the result of image processing filter as new image. - /// - /// - /// is null or is null. - /// - /// - /// doesnt fit the dimension of the image. - /// - void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle); - - /// - /// Applies the process to the specified portion of the specified at the specified - /// location and with the specified size. - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// The target width. - /// The target height. - /// - /// The structure that specifies the location and size of the drawn image. - /// The image is scaled to fit the rectangle. - /// - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// The method keeps the source image unchanged and returns the - /// the result of image process as new image. - /// - void Apply(ImageBase target, ImageBase source, int width, int height, Rectangle targetRectangle, Rectangle sourceRectangle); - } -} diff --git a/src/ImageSharp46/Samplers/Processors/ImageSampler.cs b/src/ImageSharp46/Samplers/Processors/ImageSampler.cs deleted file mode 100644 index 98ffe3b88..000000000 --- a/src/ImageSharp46/Samplers/Processors/ImageSampler.cs +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - - /// - /// Encapsulates methods to alter the pixels of an image. The processor creates a copy of the original image to operate on. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class ImageSampler : ImageProcessor, IImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle) - { - try - { - this.OnApply(target, source, target.Bounds, sourceRectangle); - - this.Apply(target, source, target.Bounds, sourceRectangle, sourceRectangle.Y, sourceRectangle.Bottom); - - this.AfterApply(target, source, target.Bounds, sourceRectangle); - } - catch (Exception ex) - { - throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex); - } - } - - /// - public void Apply(ImageBase target, ImageBase source, int width, int height, Rectangle targetRectangle = default(Rectangle), Rectangle sourceRectangle = default(Rectangle)) - { - try - { - TColor[] pixels = new TColor[width * height]; - target.SetPixels(width, height, pixels); - - // Ensure we always have bounds. - if (sourceRectangle == Rectangle.Empty) - { - sourceRectangle = source.Bounds; - } - - if (targetRectangle == Rectangle.Empty) - { - targetRectangle = target.Bounds; - } - - this.OnApply(target, source, targetRectangle, sourceRectangle); - - this.Apply(target, source, targetRectangle, sourceRectangle, targetRectangle.Y, targetRectangle.Bottom); - - this.AfterApply(target, source, target.Bounds, sourceRectangle); - } - catch (Exception ex) - { - throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex); - } - } - - /// - /// Applies the process to the specified portion of the specified at the specified location - /// and with the specified size. - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// - /// The structure that specifies the location and size of the drawn image. - /// The image is scaled to fit the rectangle. - /// - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The index of the row within the source image to start processing. - /// The index of the row within the source image to end processing. - /// - /// The method keeps the source image unchanged and returns the the result of image process as new image. - /// - public abstract void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY); - - /// - /// This method is called before the process is applied to prepare the processor. - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// - /// The structure that specifies the location and size of the drawn image. - /// The image is scaled to fit the rectangle. - /// - /// - /// The structure that specifies the portion of the image object to draw. - /// - protected virtual void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - } - - /// - /// This method is called after the process is applied to prepare the processor. - /// - /// Target image to apply the process to. - /// The source image. Cannot be null. - /// - /// The structure that specifies the location and size of the drawn image. - /// The image is scaled to fit the rectangle. - /// - /// - /// The structure that specifies the portion of the image object to draw. - /// - protected virtual void AfterApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/Matrix3x2Processor.cs b/src/ImageSharp46/Samplers/Processors/Matrix3x2Processor.cs deleted file mode 100644 index a9b460d43..000000000 --- a/src/ImageSharp46/Samplers/Processors/Matrix3x2Processor.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Numerics; - - /// - /// Provides methods to transform an image using a . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class Matrix3x2Processor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Creates a new target to contain the results of the matrix transform. - /// - /// Target image to apply the process to. - /// The source rectangle. - /// The processing matrix. - protected static void CreateNewTarget(ImageBase target, Rectangle sourceRectangle, Matrix3x2 processMatrix) - { - Matrix3x2 sizeMatrix; - if (Matrix3x2.Invert(processMatrix, out sizeMatrix)) - { - Rectangle rectangle = ImageMaths.GetBoundingRectangle(sourceRectangle, sizeMatrix); - target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]); - } - } - - /// - /// Gets a transform matrix adjusted to center upon the target image bounds. - /// - /// Target image to apply the process to. - /// The source image. - /// The transform matrix. - /// - /// The . - /// - protected static Matrix3x2 GetCenteredMatrix(ImageBase target, ImageBase source, Matrix3x2 matrix) - { - Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-target.Width * .5F, -target.Height * .5F); - Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F); - return (translationToTargetCenter * matrix) * translateToSourceCenter; - } - } -} diff --git a/src/ImageSharp46/Samplers/Processors/OilPaintingProcessor.cs b/src/ImageSharp46/Samplers/Processors/OilPaintingProcessor.cs deleted file mode 100644 index ee0d4121a..000000000 --- a/src/ImageSharp46/Samplers/Processors/OilPaintingProcessor.cs +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to apply an oil painting effect to an . - /// - /// Adapted from by Dewald Esterhuizen. - /// The pixel format. - /// The packed format. uint, long, float. - public class OilPaintingProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The number of intensity levels. Higher values result in a broader range of colour intensities forming part of the result image. - /// The number of neighbouring pixels used in calculating each individual pixel value. - public OilPaintingProcessor(int levels, int brushSize) - { - Guard.MustBeGreaterThan(levels, 0, nameof(levels)); - Guard.MustBeGreaterThan(brushSize, 0, nameof(brushSize)); - - this.Levels = levels; - this.BrushSize = brushSize; - } - - /// - /// Gets the intensity levels - /// - public int Levels { get; } - - /// - /// Gets the brush size - /// - public int BrushSize { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int radius = this.BrushSize >> 1; - int levels = this.Levels; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - for (int x = startX; x < endX; x++) - { - int maxIntensity = 0; - int maxIndex = 0; - - int[] intensityBin = new int[levels]; - float[] redBin = new float[levels]; - float[] blueBin = new float[levels]; - float[] greenBin = new float[levels]; - - for (int fy = 0; fy <= radius; fy++) - { - int fyr = fy - radius; - int offsetY = y + fyr; - - // Skip the current row - if (offsetY < minY) - { - continue; - } - - // Outwith the current bounds so break. - if (offsetY >= maxY) - { - break; - } - - for (int fx = 0; fx <= radius; fx++) - { - int fxr = fx - radius; - int offsetX = x + fxr; - - // Skip the column - if (offsetX < 0) - { - continue; - } - - if (offsetX < maxX) - { - // ReSharper disable once AccessToDisposedClosure - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); - - float sourceRed = color.X; - float sourceBlue = color.Z; - float sourceGreen = color.Y; - - int currentIntensity = (int)Math.Round((sourceBlue + sourceGreen + sourceRed) / 3.0 * (levels - 1)); - - intensityBin[currentIntensity] += 1; - blueBin[currentIntensity] += sourceBlue; - greenBin[currentIntensity] += sourceGreen; - redBin[currentIntensity] += sourceRed; - - if (intensityBin[currentIntensity] > maxIntensity) - { - maxIntensity = intensityBin[currentIntensity]; - maxIndex = currentIntensity; - } - } - } - - float red = Math.Abs(redBin[maxIndex] / maxIntensity); - float green = Math.Abs(greenBin[maxIndex] / maxIntensity); - float blue = Math.Abs(blueBin[maxIndex] / maxIntensity); - - Vector4 targetColor = targetPixels[x, y].ToVector4(); - TColor packed = default(TColor); - packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z)); - targetPixels[x, y] = packed; - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/PixelateProcessor.cs b/src/ImageSharp46/Samplers/Processors/PixelateProcessor.cs deleted file mode 100644 index 2c1875909..000000000 --- a/src/ImageSharp46/Samplers/Processors/PixelateProcessor.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - - /// - /// An to pixelate the colors of an . - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class PixelateProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// The size of the pixels. Must be greater than 0. - /// - /// is less than 0 or equal to 0. - /// - public PixelateProcessor(int size) - { - Guard.MustBeGreaterThan(size, 0, nameof(size)); - this.Value = size; - } - - /// - /// Gets or the pixel size. - /// - public int Value { get; } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int size = this.Value; - int offset = this.Value / 2; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - // Get the range on the y-plane to choose from. - IEnumerable range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.ForEach( - range, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - int offsetPy = offset; - - for (int x = minX; x < maxX; x += size) - { - int offsetX = x - startX; - int offsetPx = offset; - - // Make sure that the offset is within the boundary of the image. - while (offsetY + offsetPy >= maxY) - { - offsetPy--; - } - - while (x + offsetPx >= maxX) - { - offsetPx--; - } - - // Get the pixel color in the centre of the soon to be pixelated area. - // ReSharper disable AccessToDisposedClosure - TColor pixel = sourcePixels[offsetX + offsetPx, offsetY + offsetPy]; - - // For each pixel in the pixelate size, set it to the centre color. - for (int l = offsetY; l < offsetY + size && l < maxY; l++) - { - for (int k = offsetX; k < offsetX + size && k < maxX; k++) - { - targetPixels[k, l] = pixel; - } - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/ResamplingWeightedProcessor.cs b/src/ImageSharp46/Samplers/Processors/ResamplingWeightedProcessor.cs deleted file mode 100644 index 1d9d3da35..000000000 --- a/src/ImageSharp46/Samplers/Processors/ResamplingWeightedProcessor.cs +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - - /// - /// Provides methods that allow the resizing of images using various algorithms. - /// Adapted from - /// - /// The pixel format. - /// The packed format. uint, long, float. - public abstract class ResamplingWeightedProcessor : ImageSampler - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The sampler to perform the resize operation. - /// - protected ResamplingWeightedProcessor(IResampler sampler) - { - Guard.NotNull(sampler, nameof(sampler)); - - this.Sampler = sampler; - } - - /// - /// Gets the sampler to perform the resize operation. - /// - public IResampler Sampler { get; } - - /// - /// Gets or sets the horizontal weights. - /// - protected Weights[] HorizontalWeights { get; set; } - - /// - /// Gets or sets the vertical weights. - /// - protected Weights[] VerticalWeights { get; set; } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (!(this.Sampler is NearestNeighborResampler)) - { - this.HorizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width); - this.VerticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height); - } - } - - /// - protected override void AfterApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - // Copy the pixels over. - if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle) - { - target.ClonePixels(target.Width, target.Height, source.Pixels); - } - } - - /// - /// Computes the weights to apply at each pixel when resizing. - /// - /// The destination section size. - /// The source section size. - /// - /// The . - /// - protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize) - { - float ratio = (float)sourceSize / destinationSize; - float scale = ratio; - - if (scale < 1F) - { - scale = 1F; - } - - IResampler sampler = this.Sampler; - float radius = (float)Math.Ceiling(scale * sampler.Radius); - Weights[] result = new Weights[destinationSize]; - - for (int i = 0; i < destinationSize; i++) - { - float center = ((i + .5F) * ratio) - .5F; - - // Keep inside bounds. - int left = (int)Math.Ceiling(center - radius); - if (left < 0) - { - left = 0; - } - - int right = (int)Math.Floor(center + radius); - if (right > sourceSize - 1) - { - right = sourceSize - 1; - } - - float sum = 0; - result[i] = new Weights(); - Weight[] weights = new Weight[right - left + 1]; - - for (int j = left; j <= right; j++) - { - float weight = sampler.GetValue((j - center) / scale); - sum += weight; - weights[j - left] = new Weight(j, weight); - } - - // Normalise, best to do it here rather than in the pixel loop later on. - if (sum > 0) - { - for (int w = 0; w < weights.Length; w++) - { - weights[w].Value = weights[w].Value / sum; - } - } - - result[i].Values = weights; - } - - return result; - } - - /// - /// Represents the weight to be added to a scaled pixel. - /// - protected class Weight - { - /// - /// Initializes a new instance of the class. - /// - /// The index. - /// The value. - public Weight(int index, float value) - { - this.Index = index; - this.Value = value; - } - - /// - /// Gets the pixel index. - /// - public int Index { get; } - - /// - /// Gets or sets the result of the interpolation algorithm. - /// - public float Value { get; set; } - } - - /// - /// Represents a collection of weights and their sum. - /// - protected class Weights - { - /// - /// Gets or sets the values. - /// - public Weight[] Values { get; set; } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/ResizeProcessor.cs b/src/ImageSharp46/Samplers/Processors/ResizeProcessor.cs deleted file mode 100644 index 82e949148..000000000 --- a/src/ImageSharp46/Samplers/Processors/ResizeProcessor.cs +++ /dev/null @@ -1,158 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the resizing of images using various algorithms. - /// - /// - /// This version and the have been separated out to improve performance. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class ResizeProcessor : ResamplingWeightedProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The sampler to perform the resize operation. - /// - public ResizeProcessor(IResampler sampler) - : base(sampler) - { - } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - // Jump out, we'll deal with that later. - if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle) - { - return; - } - - int width = target.Width; - int height = target.Height; - int sourceHeight = sourceRectangle.Height; - int targetX = target.Bounds.X; - int targetY = target.Bounds.Y; - int targetRight = target.Bounds.Right; - int targetBottom = target.Bounds.Bottom; - int startX = targetRectangle.X; - int endX = targetRectangle.Right; - - int minX = Math.Max(targetX, startX); - int maxX = Math.Min(targetRight, endX); - int minY = Math.Max(targetY, startY); - int maxY = Math.Min(targetBottom, endY); - - if (this.Sampler is NearestNeighborResampler) - { - // Scaling factors - float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width; - float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Y coordinates of source points - int originY = (int)((y - startY) * heightFactor); - - for (int x = minX; x < maxX; x++) - { - // X coordinates of source points - targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; - } - }); - } - - // Break out now. - return; - } - - // Interpolate the image using the calculated weights. - // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm - // First process the columns. Since we are not using multiple threads startY and endY - // are the upper and lower bounds of the source rectangle. - Image firstPass = new Image(target.Width, source.Height); - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor firstPassPixels = firstPass.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - minX = Math.Max(0, startX); - maxX = Math.Min(width, endX); - minY = Math.Max(0, startY); - maxY = Math.Min(height, endY); - - Parallel.For( - 0, - sourceHeight, - this.ParallelOptions, - y => - { - for (int x = minX; x < maxX; x++) - { - // Ensure offsets are normalised for cropping and padding. - Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values; - - // Destination color components - Vector4 destination = Vector4.Zero; - - for (int i = 0; i < horizontalValues.Length; i++) - { - Weight xw = horizontalValues[i]; - destination += sourcePixels[xw.Index, y].ToVector4() * xw.Value; - } - - TColor d = default(TColor); - d.PackFromVector4(destination); - firstPassPixels[x, y] = d; - } - }); - - // Now process the rows. - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Ensure offsets are normalised for cropping and padding. - Weight[] verticalValues = this.VerticalWeights[y - startY].Values; - - for (int x = 0; x < width; x++) - { - // Destination color components - Vector4 destination = Vector4.Zero; - - for (int i = 0; i < verticalValues.Length; i++) - { - Weight yw = verticalValues[i]; - destination += firstPassPixels[x, yw.Index].ToVector4() * yw.Value; - } - - TColor d = default(TColor); - d.PackFromVector4(destination); - targetPixels[x, y] = d; - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/RotateProcessor.cs b/src/ImageSharp46/Samplers/Processors/RotateProcessor.cs deleted file mode 100644 index 0fdc187bd..000000000 --- a/src/ImageSharp46/Samplers/Processors/RotateProcessor.cs +++ /dev/null @@ -1,215 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the rotating of images. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class RotateProcessor : Matrix3x2Processor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The tranform matrix to apply. - /// - private Matrix3x2 processMatrix; - - /// - /// Gets or sets the angle of processMatrix in degrees. - /// - public float Angle { get; set; } - - /// - /// Gets or sets a value indicating whether to expand the canvas to fit the rotated image. - /// - public bool Expand { get; set; } = true; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - const float Epsilon = .0001F; - - if (Math.Abs(this.Angle) < Epsilon || Math.Abs(this.Angle - 90) < Epsilon || Math.Abs(this.Angle - 180) < Epsilon || Math.Abs(this.Angle - 270) < Epsilon) - { - return; - } - - this.processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle); - if (this.Expand) - { - CreateNewTarget(target, sourceRectangle, this.processMatrix); - } - } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - if (this.OptimizedApply(target, source)) - { - return; - } - - int height = target.Height; - int width = target.Width; - Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - Point transformedPoint = Point.Rotate(new Point(x, y), matrix); - if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) - { - targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y]; - } - } - }); - } - } - - /// - /// Rotates the images with an optimized method when the angle is 90, 180 or 270 degrees. - /// - /// The target image. - /// The source image. - /// - private bool OptimizedApply(ImageBase target, ImageBase source) - { - const float Epsilon = .0001F; - if (Math.Abs(this.Angle) < Epsilon) - { - target.ClonePixels(target.Width, target.Height, source.Pixels); - return true; - } - - if (Math.Abs(this.Angle - 90) < Epsilon) - { - this.Rotate90(target, source); - return true; - } - - if (Math.Abs(this.Angle - 180) < Epsilon) - { - this.Rotate180(target, source); - return true; - } - - if (Math.Abs(this.Angle - 270) < Epsilon) - { - this.Rotate270(target, source); - return true; - } - - return false; - } - - /// - /// Rotates the image 270 degrees clockwise at the centre point. - /// - /// The target image. - /// The source image. - private void Rotate270(ImageBase target, ImageBase source) - { - int width = source.Width; - int height = source.Height; - Image temp = new Image(height, width); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor tempPixels = temp.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - newX = height - newX - 1; - int newY = width - x - 1; - tempPixels[newX, newY] = sourcePixels[x, y]; - } - }); - } - - target.SetPixels(height, width, temp.Pixels); - } - - /// - /// Rotates the image 180 degrees clockwise at the centre point. - /// - /// The target image. - /// The source image. - private void Rotate180(ImageBase target, ImageBase source) - { - int width = source.Width; - int height = source.Height; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - int newX = width - x - 1; - int newY = height - y - 1; - targetPixels[newX, newY] = sourcePixels[x, y]; - } - }); - } - } - - /// - /// Rotates the image 90 degrees clockwise at the centre point. - /// - /// The target image. - /// The source image. - private void Rotate90(ImageBase target, ImageBase source) - { - int width = source.Width; - int height = source.Height; - Image temp = new Image(height, width); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor tempPixels = temp.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - tempPixels[newX, x] = sourcePixels[x, y]; - } - }); - } - - target.SetPixels(height, width, temp.Pixels); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Processors/SkewProcessor.cs b/src/ImageSharp46/Samplers/Processors/SkewProcessor.cs deleted file mode 100644 index b21301a87..000000000 --- a/src/ImageSharp46/Samplers/Processors/SkewProcessor.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the skewing of images. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class SkewProcessor : Matrix3x2Processor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - /// The tranform matrix to apply. - /// - private Matrix3x2 processMatrix; - - /// - /// Gets or sets the angle of rotation along the x-axis in degrees. - /// - public float AngleX { get; set; } - - /// - /// Gets or sets the angle of rotation along the y-axis in degrees. - /// - public float AngleY { get; set; } - - /// - /// Gets or sets a value indicating whether to expand the canvas to fit the skewed image. - /// - public bool Expand { get; set; } = true; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - this.processMatrix = Point.CreateSkew(new Point(0, 0), -this.AngleX, -this.AngleY); - if (this.Expand) - { - CreateNewTarget(target, sourceRectangle, this.processMatrix); - } - } - - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int height = target.Height; - int width = target.Width; - Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - Point transformedPoint = Point.Skew(new Point(x, y), matrix); - if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) - { - targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y]; - } - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp46/Samplers/Resamplers/BicubicResampler.cs b/src/ImageSharp46/Samplers/Resamplers/BicubicResampler.cs deleted file mode 100644 index a0bfc1413..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/BicubicResampler.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the bicubic kernel algorithm W(x) as described on - /// Wikipedia - /// A commonly used algorithm within imageprocessing that preserves sharpness better than triangle interpolation. - /// - public class BicubicResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - float result = 0; - - // Given the coefficient "a" as -0.5F. - if (x <= 1F) - { - // Below simplified result = ((a + 2F) * (x * x * x)) - ((a + 3F) * (x * x)) + 1; - result = (((1.5F * x) - 2.5F) * x * x) + 1; - } - else if (x < 2F) - { - // Below simplified result = (a * (x * x * x)) - ((5F * a) * (x * x)) + ((8F * a) * x) - (4F * a); - result = (((((-0.5F * x) + 2.5F) * x) - 4) * x) + 2; - } - - return result; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/BoxResampler.cs b/src/ImageSharp46/Samplers/Resamplers/BoxResampler.cs deleted file mode 100644 index adb238a19..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/BoxResampler.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the box algorithm. Similar to nearest neighbour when upscaling. - /// When downscaling the pixels will average, merging together. - /// - public class BoxResampler : IResampler - { - /// - public float Radius => 0.5F; - - /// - public float GetValue(float x) - { - if (x > -0.5F && x <= 0.5F) - { - return 1; - } - - return 0; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/CatmullRomResampler.cs b/src/ImageSharp46/Samplers/Resamplers/CatmullRomResampler.cs deleted file mode 100644 index 7751aa08b..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/CatmullRomResampler.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The Catmull-Rom filter is a well known standard Cubic Filter often used as a interpolation function. - /// This filter produces a reasonably sharp edge, but without a the pronounced gradient change on large - /// scale image enlargements that a 'Lagrange' filter can produce. - /// - /// - public class CatmullRomResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0; - const float C = 0.5F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/HermiteResampler.cs b/src/ImageSharp46/Samplers/Resamplers/HermiteResampler.cs deleted file mode 100644 index 9af35e8e8..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/HermiteResampler.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - /// - /// The Hermite filter is type of smoothed triangular interpolation Filter, - /// This filter rounds off strong edges while preserving flat 'color levels' in the original image. - /// - /// - public class HermiteResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0F; - const float C = 0F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/IResampler.cs b/src/ImageSharp46/Samplers/Resamplers/IResampler.cs deleted file mode 100644 index ce100a8c7..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/IResampler.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Encapsulates an interpolation algorithm for resampling images. - /// - public interface IResampler - { - /// - /// Gets the radius in which to sample pixels. - /// - float Radius { get; } - - /// - /// Gets the result of the interpolation algorithm. - /// - /// The value to process. - /// - /// The - /// - float GetValue(float x); - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/Lanczos2Resampler.cs b/src/ImageSharp46/Samplers/Resamplers/Lanczos2Resampler.cs deleted file mode 100644 index 3d25cf859..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/Lanczos2Resampler.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Lanczos kernel algorithm as described on - /// Wikipedia - /// with a radius of 2 pixels. - /// - public class Lanczos2Resampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 2F) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 2F); - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/Lanczos3Resampler.cs b/src/ImageSharp46/Samplers/Resamplers/Lanczos3Resampler.cs deleted file mode 100644 index f771de1a5..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/Lanczos3Resampler.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Lanczos kernel algorithm as described on - /// Wikipedia - /// with a radius of 3 pixels. - /// - public class Lanczos3Resampler : IResampler - { - /// - public float Radius => 3; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 3F) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3F); - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/Lanczos5Resampler.cs b/src/ImageSharp46/Samplers/Resamplers/Lanczos5Resampler.cs deleted file mode 100644 index 4584b258f..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/Lanczos5Resampler.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Lanczos kernel algorithm as described on - /// Wikipedia - /// with a radius of 5 pixels. - /// - public class Lanczos5Resampler : IResampler - { - /// - public float Radius => 5; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 5F) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 5F); - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/Lanczos8Resampler.cs b/src/ImageSharp46/Samplers/Resamplers/Lanczos8Resampler.cs deleted file mode 100644 index 03f5a6d7b..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/Lanczos8Resampler.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Lanczos kernel algorithm as described on - /// Wikipedia - /// with a radius of 8 pixels. - /// - public class Lanczos8Resampler : IResampler - { - /// - public float Radius => 8; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 8F) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 8F); - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/MitchellNetravaliResampler.cs b/src/ImageSharp46/Samplers/Resamplers/MitchellNetravaliResampler.cs deleted file mode 100644 index f4bc3a6f2..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/MitchellNetravaliResampler.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the mitchell algorithm as described on - /// Wikipedia - /// - public class MitchellNetravaliResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.3333333F; - const float C = 0.3333333F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/NearestNeighborResampler.cs b/src/ImageSharp46/Samplers/Resamplers/NearestNeighborResampler.cs deleted file mode 100644 index ec2417f9c..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/NearestNeighborResampler.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the nearest neighbour algorithm. This uses an unscaled filter - /// which will select the closest pixel to the new pixels position. - /// - public class NearestNeighborResampler : IResampler - { - /// - public float Radius => 1; - - /// - public float GetValue(float x) - { - return x; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/RobidouxResampler.cs b/src/ImageSharp46/Samplers/Resamplers/RobidouxResampler.cs deleted file mode 100644 index 6ef90bda4..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/RobidouxResampler.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Robidoux algorithm. - /// - /// - public class RobidouxResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.37821575509399867F; - const float C = 0.31089212245300067F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/RobidouxSharpResampler.cs b/src/ImageSharp46/Samplers/Resamplers/RobidouxSharpResampler.cs deleted file mode 100644 index 8755bf3e4..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/RobidouxSharpResampler.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the Robidoux Sharp algorithm. - /// - /// - public class RobidouxSharpResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.2620145123990142F; - const float C = 0.3689927438004929F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/SplineResampler.cs b/src/ImageSharp46/Samplers/Resamplers/SplineResampler.cs deleted file mode 100644 index 921ea23a8..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/SplineResampler.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the spline algorithm. - /// - /// - public class SplineResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 1F; - const float C = 0F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/TriangleResampler.cs b/src/ImageSharp46/Samplers/Resamplers/TriangleResampler.cs deleted file mode 100644 index c53d5a146..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/TriangleResampler.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the triangle (bilinear) algorithm. - /// Bilinear interpolation can be used where perfect image transformation with pixel matching is impossible, - /// so that one can calculate and assign appropriate intensity values to pixels. - /// - public class TriangleResampler : IResampler - { - /// - public float Radius => 1; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 1F) - { - return 1F - x; - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resamplers/WelchResampler.cs b/src/ImageSharp46/Samplers/Resamplers/WelchResampler.cs deleted file mode 100644 index eb5506151..000000000 --- a/src/ImageSharp46/Samplers/Resamplers/WelchResampler.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// The function implements the welch algorithm. - /// - /// - public class WelchResampler : IResampler - { - /// - public float Radius => 3; - - /// - public float GetValue(float x) - { - if (x < 0F) - { - x = -x; - } - - if (x < 3F) - { - return ImageMaths.SinC(x) * (1F - (x * x / 9.0F)); - } - - return 0F; - } - } -} diff --git a/src/ImageSharp46/Samplers/Resize.cs b/src/ImageSharp46/Samplers/Resize.cs deleted file mode 100644 index ee3da5ec6..000000000 --- a/src/ImageSharp46/Samplers/Resize.cs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Resizes an image in accordance with the given . - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The resize options. - /// The - /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, ResizeOptions options) - where TColor : struct, IPackedPixel - where TPacked : struct - { - // Ensure size is populated across both dimensions. - if (options.Size.Width == 0 && options.Size.Height > 0) - { - options.Size = new Size(source.Width * options.Size.Height / source.Height, options.Size.Height); - } - - if (options.Size.Height == 0 && options.Size.Width > 0) - { - options.Size = new Size(options.Size.Width, source.Height * options.Size.Width / source.Width); - } - - Rectangle targetRectangle = ResizeHelper.CalculateTargetLocationAndBounds(source, options); - - return Resize(source, options.Size.Width, options.Size.Height, options.Sampler, source.Bounds, targetRectangle, options.Compand); - } - - /// - /// Resizes an image to the given width and height. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// The - /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Resize(source, width, height, new BicubicResampler(), false); - } - - /// - /// Resizes an image to the given width and height. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The - /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height, bool compand) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Resize(source, width, height, new BicubicResampler(), compand); - } - - /// - /// Resizes an image to the given width and height with the given sampler. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// The to perform the resampling. - /// The - /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height, IResampler sampler) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Resize(source, width, height, sampler, false); - } - - /// - /// Resizes an image to the given width and height with the given sampler. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// The to perform the resampling. - /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The - /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height, IResampler sampler, bool compand) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Resize(source, width, height, sampler, source.Bounds, new Rectangle(0, 0, width, height), compand); - } - - /// - /// Resizes an image to the given width and height with the given sampler and - /// source rectangle. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to resize. - /// The target image width. - /// The target image height. - /// The to perform the resampling. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// The structure that specifies the portion of the target image object to draw to. - /// - /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The - /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false) - where TColor : struct, IPackedPixel - where TPacked : struct - { - if (width == 0 && height > 0) - { - width = source.Width * height / source.Height; - targetRectangle.Width = width; - } - - if (height == 0 && width > 0) - { - height = source.Height * width / source.Width; - targetRectangle.Height = height; - } - - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - - ResamplingWeightedProcessor processor; - - if (compand) - { - processor = new CompandingResizeProcessor(sampler); - } - else - { - processor = new ResizeProcessor(sampler); - } - - return source.Process(width, height, sourceRectangle, targetRectangle, processor); - } - } -} diff --git a/src/ImageSharp46/Samplers/Rotate.cs b/src/ImageSharp46/Samplers/Rotate.cs deleted file mode 100644 index f8f0a59e8..000000000 --- a/src/ImageSharp46/Samplers/Rotate.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Rotates an image by the given angle in degrees, expanding the image to fit the rotated result. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to rotate. - /// The angle in degrees to perform the rotation. - /// The - public static Image Rotate(this Image source, float degrees) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Rotate(source, degrees, true); - } - - /// - /// Rotates and flips an image by the given instructions. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to rotate. - /// The to perform the rotation. - /// The - public static Image Rotate(this Image source, RotateType rotateType) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Rotate(source, (float)rotateType, false); - } - - /// - /// Rotates an image by the given angle in degrees. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to rotate. - /// The angle in degrees to perform the rotation. - /// Whether to expand the image to fit the rotated result. - /// The - public static Image Rotate(this Image source, float degrees, bool expand) - where TColor : struct, IPackedPixel - where TPacked : struct - { - RotateProcessor processor = new RotateProcessor { Angle = degrees, Expand = expand }; - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - } -} diff --git a/src/ImageSharp46/Samplers/RotateFlip.cs b/src/ImageSharp46/Samplers/RotateFlip.cs deleted file mode 100644 index 5adef987c..000000000 --- a/src/ImageSharp46/Samplers/RotateFlip.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Rotates and flips an image by the given instructions. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to rotate, flip, or both. - /// The to perform the rotation. - /// The to perform the flip. - /// The - public static Image RotateFlip(this Image source, RotateType rotateType, FlipType flipType) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return source.Rotate(rotateType).Flip(flipType); - } - } -} diff --git a/src/ImageSharp46/Samplers/Skew.cs b/src/ImageSharp46/Samplers/Skew.cs deleted file mode 100644 index 4aa756842..000000000 --- a/src/ImageSharp46/Samplers/Skew.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Skews an image by the given angles in degrees, expanding the image to fit the skewed result. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. - /// The - public static Image Skew(this Image source, float degreesX, float degreesY) - where TColor : struct, IPackedPixel - where TPacked : struct - { - return Skew(source, degreesX, degreesY, true); - } - - /// - /// Skews an image by the given angles in degrees. - /// - /// The pixel format. - /// The packed format. uint, long, float. - /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. - /// Whether to expand the image to fit the skewed result. - /// The - public static Image Skew(this Image source, float degreesX, float degreesY, bool expand) - where TColor : struct, IPackedPixel - where TPacked : struct - { - SkewProcessor processor = new SkewProcessor { AngleX = degreesX, AngleY = degreesY, Expand = expand }; - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - } -} diff --git a/src/ImageSharp46/app.config b/src/ImageSharp46/app.config deleted file mode 100644 index 5e95024db..000000000 --- a/src/ImageSharp46/app.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageSharp46/packages.config b/src/ImageSharp46/packages.config deleted file mode 100644 index 6ace6583b..000000000 --- a/src/ImageSharp46/packages.config +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs b/tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs deleted file mode 100644 index 6de820f8b..000000000 --- a/tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using ImageSharp.Tests; -using Xunit; -using Xunit.Abstractions; - -namespace ImageSharp.Tests46.Benchmark -{ - using System.Drawing; - using System.IO; - - using CoreImage = ImageSharp.Image; - using CoreSize = ImageSharp.Size; - - public class DecodeJpegBenchmark - { - private static byte[] jpegBytes = File.ReadAllBytes(TestImages.Jpeg.Calliphora); - - private ITestOutputHelper _output; - - public DecodeJpegBenchmark(ITestOutputHelper output) - { - _output = output; - } - - private void DoBenchmark(int times, Action action, [CallerMemberName]string method = null) - { - _output.WriteLine($"{method} x {times} ... "); - Stopwatch sw = Stopwatch.StartNew(); - for (int i = 0; i < times; i++) - { - using (MemoryStream memoryStream = new MemoryStream(jpegBytes)) - { - action(memoryStream); - } - } - sw.Stop(); - var millis = sw.ElapsedMilliseconds; - - _output.WriteLine($"{method} finished in {millis}ms"); - } - - [Theory] - [InlineData(10)] - [InlineData(100)] - public void JpegSystemDrawing(int times) - { - DoBenchmark(times, memoryStream => - { - Image image = Image.FromStream(memoryStream); - image.Dispose(); - }); - } - - [Theory] - [InlineData(10)] - [InlineData(100)] - public void JpegCore(int times) - { - DoBenchmark(times, memoryStream => - { - CoreImage image = new CoreImage(memoryStream); - }); - } - - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Colors/ColorConversionTests.cs b/tests/ImageSharp.Tests46/Colors/ColorConversionTests.cs deleted file mode 100644 index f1b6d5f9b..000000000 --- a/tests/ImageSharp.Tests46/Colors/ColorConversionTests.cs +++ /dev/null @@ -1,511 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.Diagnostics.CodeAnalysis; - - using Xunit; - - /// - /// Test conversion between the various color structs. - /// - /// - /// Output values have been compared with - /// and for accuracy. - /// - public class ColorConversionTests - { - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToYCbCr() - { - // White - Color color = Color.White; - YCbCr yCbCr = color; - - Assert.Equal(255, yCbCr.Y); - Assert.Equal(128, yCbCr.Cb); - Assert.Equal(128, yCbCr.Cr); - - // Black - Color color2 = Color.Black; - YCbCr yCbCr2 = color2; - Assert.Equal(0, yCbCr2.Y); - Assert.Equal(128, yCbCr2.Cb); - Assert.Equal(128, yCbCr2.Cr); - - // Gray - Color color3 = Color.Gray; - YCbCr yCbCr3 = color3; - Assert.Equal(128, yCbCr3.Y); - Assert.Equal(128, yCbCr3.Cb); - Assert.Equal(128, yCbCr3.Cr); - - //Assert.Equal(255, yCbCr.Y, 0); - //Assert.Equal(128, yCbCr.Cb, 0); - //Assert.Equal(128, yCbCr.Cr, 0); - - //// Black - //Color color2 = Color.Black; - //YCbCr yCbCr2 = color2; - //Assert.Equal(0, yCbCr2.Y, 0); - //Assert.Equal(128, yCbCr2.Cb, 0); - //Assert.Equal(128, yCbCr2.Cr, 0); - - //// Gray - //Color color3 = Color.Gray; - //YCbCr yCbCr3 = color3; - //Assert.Equal(128, yCbCr3.Y, 0); - //Assert.Equal(128, yCbCr3.Cb, 0); - //Assert.Equal(128, yCbCr3.Cr, 0); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void YCbCrToColor() - { - // White - YCbCr yCbCr = new YCbCr(255, 128, 128); - Color color = yCbCr; - - Assert.Equal(255, color.R); - Assert.Equal(255, color.G); - Assert.Equal(255, color.B); - Assert.Equal(255, color.A); - - // Black - YCbCr yCbCr2 = new YCbCr(0, 128, 128); - Color color2 = yCbCr2; - - Assert.Equal(0, color2.R); - Assert.Equal(0, color2.G); - Assert.Equal(0, color2.B); - Assert.Equal(255, color2.A); - - // Gray - YCbCr yCbCr3 = new YCbCr(128, 128, 128); - Color color3 = yCbCr3; - - Assert.Equal(128, color3.R); - Assert.Equal(128, color3.G); - Assert.Equal(128, color3.B); - Assert.Equal(255, color3.A); - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-xyz - /// - [Fact] - public void ColorToCieXyz() - { - // White - Color color = Color.White; - CieXyz ciexyz = color; - - Assert.Equal(95.05f, ciexyz.X, 3); - Assert.Equal(100.0f, ciexyz.Y, 3); - Assert.Equal(108.900f, ciexyz.Z, 3); - - // Black - Color color2 = Color.Black; - CieXyz ciexyz2 = color2; - Assert.Equal(0, ciexyz2.X, 3); - Assert.Equal(0, ciexyz2.Y, 3); - Assert.Equal(0, ciexyz2.Z, 3); - - // Gray - Color color3 = Color.Gray; - CieXyz ciexyz3 = color3; - Assert.Equal(20.518, ciexyz3.X, 3); - Assert.Equal(21.586, ciexyz3.Y, 3); - Assert.Equal(23.507, ciexyz3.Z, 3); - - // Cyan - Color color4 = Color.Cyan; - CieXyz ciexyz4 = color4; - Assert.Equal(53.810f, ciexyz4.X, 3); - Assert.Equal(78.740f, ciexyz4.Y, 3); - Assert.Equal(106.970f, ciexyz4.Z, 3); - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-xyz - /// - [Fact] - public void CieXyzToColor() - { - // Dark moderate pink. - CieXyz ciexyz = new CieXyz(13.337f, 9.297f, 14.727f); - Color color = ciexyz; - - Assert.Equal(128, color.R); - Assert.Equal(64, color.G); - Assert.Equal(106, color.B); - - // Ochre - CieXyz ciexyz2 = new CieXyz(31.787f, 26.147f, 4.885f); - Color color2 = ciexyz2; - - Assert.Equal(204, color2.R); - Assert.Equal(119, color2.G); - Assert.Equal(34, color2.B); - - // Black - CieXyz ciexyz3 = new CieXyz(0, 0, 0); - Color color3 = ciexyz3; - - Assert.Equal(0, color3.R); - Assert.Equal(0, color3.G); - Assert.Equal(0, color3.B); - - //// Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // CieXyz ciexyz4 = color4; - // Assert.Equal(color4, (Color)ciexyz4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToHsv() - { - // Black - Color b = Color.Black; - Hsv h = b; - - Assert.Equal(0, h.H, 1); - Assert.Equal(0, h.S, 1); - Assert.Equal(0, h.V, 1); - - // White - Color color = Color.White; - Hsv hsv = color; - - Assert.Equal(0f, hsv.H, 1); - Assert.Equal(0f, hsv.S, 1); - Assert.Equal(1f, hsv.V, 1); - - // Dark moderate pink. - Color color2 = new Color(128, 64, 106); - Hsv hsv2 = color2; - - Assert.Equal(320.6f, hsv2.H, 1); - Assert.Equal(0.5f, hsv2.S, 1); - Assert.Equal(0.502f, hsv2.V, 2); - - // Ochre. - Color color3 = new Color(204, 119, 34); - Hsv hsv3 = color3; - - Assert.Equal(30f, hsv3.H, 1); - Assert.Equal(0.833f, hsv3.S, 3); - Assert.Equal(0.8f, hsv3.V, 1); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void HsvToColor() - { - // Dark moderate pink. - Hsv hsv = new Hsv(320.6f, 0.5f, 0.502f); - Color color = hsv; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Hsv hsv2 = new Hsv(30, 0.833f, 0.8f); - Color color2 = hsv2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Hsv hsv3 = new Hsv(0, 0, 1); - Color color3 = hsv3; - - Assert.Equal(color3.B, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.R, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Hsv hsv4 = color4; - // Assert.Equal(color4, (Color)hsv4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToHsl() - { - // Black - Color b = Color.Black; - Hsl h = b; - - Assert.Equal(0, h.H, 1); - Assert.Equal(0, h.S, 1); - Assert.Equal(0, h.L, 1); - - // White - Color color = Color.White; - Hsl hsl = color; - - Assert.Equal(0f, hsl.H, 1); - Assert.Equal(0f, hsl.S, 1); - Assert.Equal(1f, hsl.L, 1); - - // Dark moderate pink. - Color color2 = new Color(128, 64, 106); - Hsl hsl2 = color2; - - Assert.Equal(320.6f, hsl2.H, 1); - Assert.Equal(0.33f, hsl2.S, 1); - Assert.Equal(0.376f, hsl2.L, 2); - - // Ochre. - Color color3 = new Color(204, 119, 34); - Hsl hsl3 = color3; - - Assert.Equal(30f, hsl3.H, 1); - Assert.Equal(0.714f, hsl3.S, 3); - Assert.Equal(0.467f, hsl3.L, 3); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void HslToColor() - { - // Dark moderate pink. - Hsl hsl = new Hsl(320.6f, 0.33f, 0.376f); - Color color = hsl; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Hsl hsl2 = new Hsl(30, 0.714f, 0.467f); - Color color2 = hsl2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Hsl hsl3 = new Hsl(0, 0, 1); - Color color3 = hsl3; - - Assert.Equal(color3.R, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.B, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Hsl hsl4 = color4; - // Assert.Equal(color4, (Color)hsl4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToCmyk() - { - // White - Color color = Color.White; - Cmyk cmyk = color; - - Assert.Equal(0, cmyk.C, 1); - Assert.Equal(0, cmyk.M, 1); - Assert.Equal(0, cmyk.Y, 1); - Assert.Equal(0, cmyk.K, 1); - - // Black - Color color2 = Color.Black; - Cmyk cmyk2 = color2; - Assert.Equal(0, cmyk2.C, 1); - Assert.Equal(0, cmyk2.M, 1); - Assert.Equal(0, cmyk2.Y, 1); - Assert.Equal(1, cmyk2.K, 1); - - // Gray - Color color3 = Color.Gray; - Cmyk cmyk3 = color3; - Assert.Equal(0f, cmyk3.C, 1); - Assert.Equal(0f, cmyk3.M, 1); - Assert.Equal(0f, cmyk3.Y, 1); - Assert.Equal(0.498, cmyk3.K, 2); // Checked with other online converters. - - // Cyan - Color color4 = Color.Cyan; - Cmyk cmyk4 = color4; - Assert.Equal(1, cmyk4.C, 1); - Assert.Equal(0f, cmyk4.M, 1); - Assert.Equal(0f, cmyk4.Y, 1); - Assert.Equal(0f, cmyk4.K, 1); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void CmykToColor() - { - // Dark moderate pink. - Cmyk cmyk = new Cmyk(0f, .5f, .171f, .498f); - Color color = cmyk; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Cmyk cmyk2 = new Cmyk(0, .416f, .833f, .199f); - Color color2 = cmyk2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Cmyk cmyk3 = new Cmyk(0, 0, 0, 0); - Color color3 = cmyk3; - - Assert.Equal(color3.R, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.B, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Cmyk cmyk4 = color4; - // Assert.Equal(color4, (Color)cmyk4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-lab - /// - [Fact] - public void ColorToCieLab() - { - // White - Color color = Color.White; - CieLab cielab = color; - - Assert.Equal(100, cielab.L, 3); - Assert.Equal(0.005, cielab.A, 3); - Assert.Equal(-0.010, cielab.B, 3); - - // Black - Color color2 = Color.Black; - CieLab cielab2 = color2; - Assert.Equal(0, cielab2.L, 3); - Assert.Equal(0, cielab2.A, 3); - Assert.Equal(0, cielab2.B, 3); - - // Gray - Color color3 = Color.Gray; - CieLab cielab3 = color3; - Assert.Equal(53.585, cielab3.L, 3); - Assert.Equal(0.003, cielab3.A, 3); - Assert.Equal(-0.006, cielab3.B, 3); - - // Cyan - Color color4 = Color.Cyan; - CieLab cielab4 = color4; - Assert.Equal(91.117, cielab4.L, 3); - Assert.Equal(-48.080, cielab4.A, 3); - Assert.Equal(-14.138, cielab4.B, 3); - } - - /// - /// Tests the implicit conversion from to . - /// - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-lab - [Fact] - public void CieLabToColor() - { - // Dark moderate pink. - CieLab cielab = new CieLab(36.5492f, 33.3173f, -12.0615f); - Color color = cielab; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - CieLab cielab2 = new CieLab(58.1758f, 27.3399f, 56.8240f); - Color color2 = cielab2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // Black - CieLab cielab3 = new CieLab(0, 0, 0); - Color color3 = cielab3; - - Assert.Equal(color3.R, 0); - Assert.Equal(color3.G, 0); - Assert.Equal(color3.B, 0); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // CieLab cielab4 = color4; - // Assert.Equal(color4, (Color)cielab4); - //} - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Colors/ColorTests.cs b/tests/ImageSharp.Tests46/Colors/ColorTests.cs deleted file mode 100644 index 23ebbec98..000000000 --- a/tests/ImageSharp.Tests46/Colors/ColorTests.cs +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Numerics; - -namespace ImageSharp.Tests -{ - using System; - using Xunit; - - /// - /// Tests the struct. - /// - public class ColorTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - Color color1 = new Color(0, 0, 0); - Color color2 = new Color(0, 0, 0, 1F); - Color color3 = new Color("#000"); - Color color4 = new Color("#000F"); - Color color5 = new Color("#000000"); - Color color6 = new Color("#000000FF"); - - Assert.Equal(color1, color2); - Assert.Equal(color1, color3); - Assert.Equal(color1, color4); - Assert.Equal(color1, color5); - Assert.Equal(color1, color6); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - Color color1 = new Color(255, 0, 0, 255); - Color color2 = new Color(0, 0, 0, 255); - Color color3 = new Color("#000"); - Color color4 = new Color("#000000"); - Color color5 = new Color("#FF000000"); - - Assert.NotEqual(color1, color2); - Assert.NotEqual(color1, color3); - Assert.NotEqual(color1, color4); - Assert.NotEqual(color1, color5); - } - - /// - /// Tests whether the color constructor correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - Color color1 = new Color(1, .1f, .133f, .864f); - Assert.Equal(255, color1.R); - Assert.Equal((byte)Math.Round(.1f * 255), color1.G); - Assert.Equal((byte)Math.Round(.133f * 255), color1.B); - Assert.Equal((byte)Math.Round(.864f * 255), color1.A); - - Color color2 = new Color(1, .1f, .133f); - Assert.Equal(255, color2.R); - Assert.Equal(Math.Round(.1f * 255), color2.G); - Assert.Equal(Math.Round(.133f * 255), color2.B); - Assert.Equal(255, color2.A); - - Color color3 = new Color("#FF0000"); - Assert.Equal(255, color3.R); - Assert.Equal(0, color3.G); - Assert.Equal(0, color3.B); - Assert.Equal(255, color3.A); - - Color color4 = new Color(new Vector3(1, .1f, .133f)); - Assert.Equal(255, color4.R); - Assert.Equal(Math.Round(.1f * 255), color4.G); - Assert.Equal(Math.Round(.133f * 255), color4.B); - Assert.Equal(255, color4.A); - - Color color5 = new Color(new Vector4(1, .1f, .133f, .5f)); - Assert.Equal(255, color5.R); - Assert.Equal(Math.Round(.1f * 255), color5.G); - Assert.Equal(Math.Round(.133f * 255), color5.B); - Assert.Equal(Math.Round(.5f * 255), color5.A); - } - - /// - /// Tests whether FromHex and ToHex work correctly. - /// - [Fact] - public void FromAndToHex() - { - Color color = Color.FromHex("#AABBCCDD"); - Assert.Equal(170, color.R); - Assert.Equal(187, color.G); - Assert.Equal(204, color.B); - Assert.Equal(221, color.A); - - color.A = 170; - color.B = 187; - color.G = 204; - color.R = 221; - - Assert.Equal("DDCCBBAA", color.ToHex()); - - color.R = 0; - - Assert.Equal("00CCBBAA", color.ToHex()); - - color.A = 255; - - Assert.Equal("00CCBBFF", color.ToHex()); - } - - /// - /// Tests that the individual byte elements are layed out in RGBA order. - /// - [Fact] - public unsafe void ByteLayout() - { - Color color = new Color(1, 2, 3, 4); - byte* colorBase = (byte*)&color; - Assert.Equal(1, colorBase[0]); - Assert.Equal(2, colorBase[1]); - Assert.Equal(3, colorBase[2]); - Assert.Equal(4, colorBase[3]); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/DctSandbox.cs b/tests/ImageSharp.Tests46/DctSandbox.cs deleted file mode 100644 index d3b1bacb2..000000000 --- a/tests/ImageSharp.Tests46/DctSandbox.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Numerics; -using System.Text; -using ImageSharp.Formats; -using Xunit; -using Xunit.Abstractions; - -namespace ImageSharp.Tests -{ - public class DctSandbox - { - - private ITestOutputHelper Output { get; } - - public DctSandbox(ITestOutputHelper output) - { - Output = output; - } - - private float[] CreateTestData() - { - float[] result =new float[64]; - for (int i = 0; i < 8; i++) - { - for (int j = 0; j < 8; j++) - { - result[i*8 + j] = i*10 + j; - } - } - return result; - } - - private void Print(float[] data) - { - StringBuilder bld = new StringBuilder(); - for (int i = 0; i < 8; i++) - { - for (int j = 0; j < 8; j++) - { - bld.Append($"{data[i * 8 + j],3} "); - } - bld.AppendLine(); - } - - Output.WriteLine(bld.ToString()); - } - - [Fact] - public void Mennyi() - { - Output.WriteLine(Vector.IsHardwareAccelerated.ToString()); - Output.WriteLine(Vector.Count.ToString()); - } - - [Fact] - public void CheckTestData() - { - var data = CreateTestData(); - - Print(data); - } - - [Fact] - public void Load_Store() - { - var data = CreateTestData(); - - var m = MagicDCT.Load(data, 1, 1); - m = Matrix4x4.Transpose(m); - - MagicDCT.Store(m, data, 4, 4); - - Print(data); - } - - [Fact] - public void Transpose8x8() - { - var data = CreateTestData(); - - Span result = new Span(64); - - MagicDCT.Transpose8x8(data, result); - - Print(result.Data); - } - - [Fact] - public void Transpose8x8_Inplace() - { - var data = CreateTestData(); - - MagicDCT.Transpose8x8(data); - - Print(data); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/FileTestBase.cs b/tests/ImageSharp.Tests46/FileTestBase.cs deleted file mode 100644 index b9a226fc8..000000000 --- a/tests/ImageSharp.Tests46/FileTestBase.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.Collections.Generic; - using System.IO; - - /// - /// The test base class for reading and writing to files. - /// - public abstract class FileTestBase - { - /// - /// The collection of image files to test against. - /// - protected static readonly List Files = new List - { - // new TestFile(TestImages.Png.P1), // Perf: Enable for local testing only - // new TestFile(TestImages.Png.Pd), // Perf: Enable for local testing only - // new TestFile(TestImages.Jpeg.Floorplan), // Perf: Enable for local testing only - new TestFile(TestImages.Jpeg.Calliphora), - // new TestFile(TestImages.Jpeg.Cmyk), // Perf: Enable for local testing only - new TestFile(TestImages.Jpeg.Turtle), - // new TestFile(TestImages.Jpeg.Fb), // Perf: Enable for local testing only - // new TestFile(TestImages.Jpeg.Progress), // Perf: Enable for local testing only - // new TestFile(TestImages.Jpeg.GammaDalaiLamaGray), // Perf: Enable for local testing only - new TestFile(TestImages.Bmp.Car), - // new TestFile(TestImages.Bmp.Neg_height), // Perf: Enable for local testing only - // new TestFile(TestImages.Png.Blur), // Perf: Enable for local testing only - // new TestFile(TestImages.Png.Indexed), // Perf: Enable for local testing only - new TestFile(TestImages.Png.Splash), - new TestFile(TestImages.Gif.Rings), - // new TestFile(TestImages.Gif.Giphy) // Perf: Enable for local testing only - }; - - protected string CreateOutputDirectory(string path) - { - path = "TestOutput/" + path; - - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - - return path; - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Formats/Bmp/BitmapTests.cs b/tests/ImageSharp.Tests46/Formats/Bmp/BitmapTests.cs deleted file mode 100644 index c91b0ad1b..000000000 --- a/tests/ImageSharp.Tests46/Formats/Bmp/BitmapTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using ImageSharp.Formats; - -namespace ImageSharp.Tests -{ - using System.IO; - - using Formats; - - using Xunit; - - public class BitmapTests : FileTestBase - { - public static readonly TheoryData BitsPerPixel - = new TheoryData - { - BmpBitsPerPixel.Pixel24 , - BmpBitsPerPixel.Pixel32 - }; - - [Theory] - [MemberData("BitsPerPixel")] - public void BitmapCanEncodeDifferentBitRates(BmpBitsPerPixel bitsPerPixel) - { - string path = CreateOutputDirectory("Bmp"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileNameWithoutExtension(bitsPerPixel); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}.bmp")) - { - image.Save(output, new BmpEncoder { BitsPerPixel = bitsPerPixel }); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests46/Formats/GeneralFormatTests.cs deleted file mode 100644 index 7d88ca6e1..000000000 --- a/tests/ImageSharp.Tests46/Formats/GeneralFormatTests.cs +++ /dev/null @@ -1,158 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.IO; - - using Xunit; - - public class GeneralFormatTests : FileTestBase - { - [Fact] - public void ResolutionShouldChange() - { - string path = CreateOutputDirectory("Resolution"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.VerticalResolution = 150; - image.HorizontalResolution = 150; - image.Save(output); - } - } - } - - [Fact] - public void ImageCanEncodeToString() - { - string path = CreateOutputDirectory("ToString"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - string filename = path + "/" + file.FileNameWithoutExtension + ".txt"; - File.WriteAllText(filename, image.ToBase64String()); - } - } - - [Fact] - public void DecodeThenEncodeImageFromStreamShouldSucceed() - { - string path = CreateOutputDirectory("Encode"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Save(output); - } - } - } - - [Fact] - public void QuantizeImageShouldPreserveMaximumColorPrecision() - { - string path = CreateOutputDirectory("Quantize"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - // Copy the original pixels to save decoding time. - Color[] pixels = new Color[image.Width * image.Height]; - Array.Copy(image.Pixels, pixels, image.Pixels.Length); - - using (FileStream output = File.OpenWrite($"{path}/Octree-{file.FileName}")) - { - image.Quantize(Quantization.Octree) - .Save(output, image.CurrentImageFormat); - - } - - image.SetPixels(image.Width, image.Height, pixels); - using (FileStream output = File.OpenWrite($"{path}/Wu-{file.FileName}")) - { - image.Quantize(Quantization.Wu) - .Save(output, image.CurrentImageFormat); - } - - image.SetPixels(image.Width, image.Height, pixels); - using (FileStream output = File.OpenWrite($"{path}/Palette-{file.FileName}")) - { - image.Quantize(Quantization.Palette) - .Save(output, image.CurrentImageFormat); - } - } - } - - [Fact] - public void ImageCanConvertFormat() - { - string path = CreateOutputDirectory("Format"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.gif")) - { - image.SaveAsGif(output); - } - - using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.bmp")) - { - image.SaveAsBmp(output); - } - - using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.jpg")) - { - image.SaveAsJpeg(output); - } - - using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png")) - { - image.SaveAsPng(output); - } - } - } - - [Fact] - public void ImageShouldPreservePixelByteOrderWhenSerialized() - { - string path = CreateOutputDirectory("Serialized"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - byte[] serialized; - using (MemoryStream memoryStream = new MemoryStream()) - { - image.Save(memoryStream); - memoryStream.Flush(); - serialized = memoryStream.ToArray(); - } - - using (MemoryStream memoryStream = new MemoryStream(serialized)) - { - Image image2 = new Image(memoryStream); - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image2.Save(output); - } - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Formats/Jpg/JpegTests.cs b/tests/ImageSharp.Tests46/Formats/Jpg/JpegTests.cs deleted file mode 100644 index 57bce1504..000000000 --- a/tests/ImageSharp.Tests46/Formats/Jpg/JpegTests.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using ImageSharp.Formats; -using Xunit; -using Xunit.Abstractions; - -namespace ImageSharp.Tests.Formats.Jpg -{ - public class JpegTests - { - - public const string TestOutputDirectory = "TestOutput/Jpeg"; - - private ITestOutputHelper Output { get; } - - public JpegTests(ITestOutputHelper output) - { - Output = output; - } - - protected string CreateTestOutputFile(string fileName) - { - if (!Directory.Exists(TestOutputDirectory)) - { - Directory.CreateDirectory(TestOutputDirectory); - } - - //string id = Guid.NewGuid().ToString().Substring(0, 4); - - string ext = Path.GetExtension(fileName); - fileName = Path.GetFileNameWithoutExtension(fileName); - - return $"{TestOutputDirectory}/{fileName}{ext}"; - } - - protected Stream CreateOutputStream(string fileName) - { - fileName = CreateTestOutputFile(fileName); - Output?.WriteLine("Opened for write: "+fileName); - return File.OpenWrite(fileName); - } - - public static IEnumerable AllJpegFiles - => TestImages.Jpeg.All.Select(fn => new object[] {fn}); - - [Theory] - [MemberData(nameof(AllJpegFiles))] - public void OpenJpeg_SaveBmp(string jpegPath) - { - string bmpFileName = Path.GetFileNameWithoutExtension(jpegPath) + ".bmp"; - - using (var inputStream = File.OpenRead(jpegPath)) - { - var image = new Image(inputStream); - - using (var outputStream = CreateOutputStream(bmpFileName)) - { - image.Save(outputStream, new BmpFormat()); - } - } - } - - public static IEnumerable AllBmpFiles - => TestImages.Jpeg.All.Select(fn => new object[] {fn}); - - [Theory] - [MemberData(nameof(AllBmpFiles))] - public void OpenBmp_SaveJpeg(string bmpPath) - { - string jpegPath = Path.GetFileNameWithoutExtension(bmpPath) + ".jpeg"; - - using (var inputStream = File.OpenRead(bmpPath)) - { - var image = new Image(inputStream); - - using (var outputStream = CreateOutputStream(jpegPath)) - { - image.Save(outputStream, new JpegFormat()); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Formats/Png/PngTests.cs b/tests/ImageSharp.Tests46/Formats/Png/PngTests.cs deleted file mode 100644 index 3c37ce898..000000000 --- a/tests/ImageSharp.Tests46/Formats/Png/PngTests.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using ImageSharp.Formats; - -namespace ImageSharp.Tests -{ - using System.IO; - - using Formats; - - using Xunit; - - public class PngTests : FileTestBase - { - - - [Fact] - public void ImageCanSaveIndexedPng() - { - string path = CreateOutputDirectory("Png"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png")) - { - image.Quality = 256; - image.Save(output, new PngFormat()); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Helpers/GuardTests.cs b/tests/ImageSharp.Tests46/Helpers/GuardTests.cs deleted file mode 100644 index ba6d5687c..000000000 --- a/tests/ImageSharp.Tests46/Helpers/GuardTests.cs +++ /dev/null @@ -1,242 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests.Helpers -{ - using System; - using System.Diagnostics.CodeAnalysis; - - using Xunit; - - /// - /// Tests the helper. - /// - public class GuardTests - { - /// - /// Tests that the method throws when the argument is null. - /// - [Fact] - public void NotNullThrowsWhenArgIsNull() - { - Assert.Throws(() => Guard.NotNull(null, "foo")); - } - - /// - /// Tests that the method throws when the argument name is empty. - /// - [Fact] - public void NotNullThrowsWhenArgNameEmpty() - { - Assert.Throws(() => Guard.NotNull(null, string.Empty)); - } - - /// - /// Tests that the method throws when the argument is empty. - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1122:UseStringEmptyForEmptyStrings", Justification = "Reviewed. Suppression is OK here.")] - public void NotEmptyThrowsWhenEmpty() - { - Assert.Throws(() => Guard.NotNullOrEmpty("", string.Empty)); - } - - /// - /// Tests that the method throws when the argument is whitespace. - /// - [Fact] - public void NotEmptyThrowsWhenWhitespace() - { - Assert.Throws(() => Guard.NotNullOrEmpty(" ", string.Empty)); - } - - /// - /// Tests that the method throws when the argument name is null. - /// - [Fact] - public void NotEmptyThrowsWhenParameterNameNull() - { - Assert.Throws(() => Guard.NotNullOrEmpty(null, null)); - } - - /// - /// Tests that the method throws when the argument is greater. - /// - [Fact] - public void LessThanThrowsWhenArgIsGreater() - { - Assert.Throws(() => Guard.MustBeLessThan(1, 0, "foo")); - } - - /// - /// Tests that the method throws when the argument is equal. - /// - [Fact] - public void LessThanThrowsWhenArgIsEqual() - { - Assert.Throws(() => Guard.MustBeLessThan(1, 1, "foo")); - } - - /// - /// Tests that the method throws when the argument is greater. - /// - [Fact] - public void LessThanOrEqualToThrowsWhenArgIsGreater() - { - Assert.Throws(() => Guard.MustBeLessThanOrEqualTo(1, 0, "foo")); - } - - /// - /// Tests that the method does not throw when the argument - /// is less. - /// - [Fact] - public void LessThanOrEqualToDoesNotThrowWhenArgIsLess() - { - Exception ex = Record.Exception(() => Guard.MustBeLessThanOrEqualTo(0, 1, "foo")); - Assert.Null(ex); - } - - /// - /// Tests that the method does not throw when the argument - /// is equal. - /// - [Fact] - public void LessThanOrEqualToDoesNotThrowWhenArgIsEqual() - { - Exception ex = Record.Exception(() => Guard.MustBeLessThanOrEqualTo(1, 1, "foo")); - Assert.Equal(1, 1); - Assert.Null(ex); - } - - /// - /// Tests that the method throws when the argument is greater. - /// - [Fact] - public void GreaterThanThrowsWhenArgIsLess() - { - Assert.Throws(() => Guard.MustBeGreaterThan(0, 1, "foo")); - } - - /// - /// Tests that the method throws when the argument is greater. - /// - [Fact] - public void GreaterThanThrowsWhenArgIsEqual() - { - Assert.Throws(() => Guard.MustBeGreaterThan(1, 1, "foo")); - } - - /// - /// Tests that the method throws when the argument name is greater. - /// - [Fact] - public void GreaterThanOrEqualToThrowsWhenArgIsLess() - { - Assert.Throws(() => Guard.MustBeGreaterThanOrEqualTo(0, 1, "foo")); - } - - /// - /// Tests that the method does not throw when the argument - /// is less. - /// - [Fact] - public void GreaterThanOrEqualToDoesNotThrowWhenArgIsGreater() - { - Exception ex = Record.Exception(() => Guard.MustBeGreaterThanOrEqualTo(1, 0, "foo")); - Assert.Null(ex); - } - - /// - /// Tests that the method does not throw when the argument - /// is equal. - /// - [Fact] - public void GreaterThanOrEqualToDoesNotThrowWhenArgIsEqual() - { - Exception ex = Record.Exception(() => Guard.MustBeGreaterThanOrEqualTo(1, 1, "foo")); - Assert.Equal(1, 1); - Assert.Null(ex); - } - - /// - /// Tests that the method throws when the argument is less. - /// - [Fact] - public void BetweenOrEqualToThrowsWhenArgIsLess() - { - Assert.Throws(() => Guard.MustBeBetweenOrEqualTo(-2, -1, 1, "foo")); - } - - /// - /// Tests that the method throws when the argument is greater. - /// - [Fact] - public void BetweenOrEqualToThrowsWhenArgIsGreater() - { - Assert.Throws(() => Guard.MustBeBetweenOrEqualTo(2, -1, 1, "foo")); - } - - /// - /// Tests that the method does not throw when the argument - /// is equal. - /// - [Fact] - public void BetweenOrEqualToDoesNotThrowWhenArgIsEqual() - { - Exception ex = Record.Exception(() => Guard.MustBeBetweenOrEqualTo(1, 1, 1, "foo")); - Assert.Null(ex); - } - - /// - /// Tests that the method does not throw when the argument - /// is equal. - /// - [Fact] - public void BetweenOrEqualToDoesNotThrowWhenArgIsBetween() - { - Exception ex = Record.Exception(() => Guard.MustBeBetweenOrEqualTo(0, -1, 1, "foo")); - Assert.Null(ex); - } - - /// - /// Tests that the method throws when the argument is false. - /// - [Fact] - public void IsTrueThrowsWhenArgIsFalse() - { - Assert.Throws(() => Guard.IsTrue(false, "foo", "message")); - } - - /// - /// Tests that the method does not throw when the argument is true. - /// - [Fact] - public void IsTrueDoesThrowsWhenArgIsTrue() - { - Exception ex = Record.Exception(() => Guard.IsTrue(true, "foo", "message")); - Assert.Null(ex); - } - - /// - /// Tests that the method throws when the argument is true. - /// - [Fact] - public void IsFalseThrowsWhenArgIsFalse() - { - Assert.Throws(() => Guard.IsFalse(true, "foo", "message")); - } - - /// - /// Tests that the method does not throw when the argument is false. - /// - [Fact] - public void IsFalseDoesThrowsWhenArgIsTrue() - { - Exception ex = Record.Exception(() => Guard.IsFalse(false, "foo", "message")); - Assert.Null(ex); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Image/ImagePropertyTests.cs b/tests/ImageSharp.Tests46/Image/ImagePropertyTests.cs deleted file mode 100644 index 8b4c6ea10..000000000 --- a/tests/ImageSharp.Tests46/Image/ImagePropertyTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using Xunit; - - /// - /// Tests the class. - /// - public class ImagePropertyTests - { - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreEqual() - { - ImageProperty property1 = new ImageProperty("Foo", "Bar"); - ImageProperty property2 = new ImageProperty("Foo", "Bar"); - ImageProperty property3 = null; - - Assert.Equal(property1, property2); - Assert.True(property1 == property2); - Assert.Equal(property3, null); - } - - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreNotEqual() - { - ImageProperty property1 = new ImageProperty("Foo", "Bar"); - ImageProperty property2 = new ImageProperty("Foo", "Foo"); - ImageProperty property3 = new ImageProperty("Bar", "Bar"); - ImageProperty property4 = new ImageProperty("Foo", null); - - Assert.False(property1.Equals("Foo")); - - Assert.NotEqual(property1, null); - - Assert.NotEqual(property1, property2); - Assert.True(property1 != property2); - - Assert.NotEqual(property1, property3); - Assert.NotEqual(property1, property4); - } - - /// - /// Tests whether the constructor throws an exception when the property name is null or empty. - /// - [Fact] - public void ConstructorThrowsWhenNameIsNullOrEmpty() - { - Assert.Throws(() => new ImageProperty(null, "Foo")); - - Assert.Throws(() => new ImageProperty(string.Empty, "Foo")); - } - - /// - /// Tests whether the constructor correctly assigns properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - ImageProperty property = new ImageProperty("Foo", null); - Assert.Equal("Foo", property.Name); - Assert.Equal(null, property.Value); - - property = new ImageProperty("Foo", string.Empty); - Assert.Equal(string.Empty, property.Value); - } - } -} diff --git a/tests/ImageSharp.Tests46/Image/PixelAccessorTests.cs b/tests/ImageSharp.Tests46/Image/PixelAccessorTests.cs deleted file mode 100644 index ab71d8de7..000000000 --- a/tests/ImageSharp.Tests46/Image/PixelAccessorTests.cs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the class. - /// - public class PixelAccessorTests - { - [Fact] - public void CopyFromZYX() - { - CopyFromZYX(new Image(1, 1)); - } - - [Fact] - public void CopyFromZYXOptimized() - { - CopyFromZYX(new Image(1, 1)); - } - - [Fact] - public void CopyFromZYXW() - { - CopyFromZYXW(new Image(1, 1)); - } - - [Fact] - public void CopyFromZYXWOptimized() - { - CopyFromZYXW(new Image(1, 1)); - } - - [Fact] - public void CopyToZYX() - { - CopyToZYX(new Image(1, 1)); - } - - [Fact] - public void CopyToZYXOptimized() - { - CopyToZYX(new Image(1, 1)); - } - - [Fact] - public void CopyToZYXW() - { - CopyToZYXW(new Image(1, 1)); - } - - [Fact] - public void CopyToZYXWOptimized() - { - CopyToZYXW(new Image(1, 1)); - } - - private static void CopyFromZYX(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - byte red = 1; - byte green = 2; - byte blue = 3; - byte alpha = 255; - - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYX)) - { - row.Bytes[0] = blue; - row.Bytes[1] = green; - row.Bytes[2] = red; - - pixels.CopyFrom(row, 0); - - Color color = (Color) (object) pixels[0, 0]; - Assert.Equal(red, color.R); - Assert.Equal(green, color.G); - Assert.Equal(blue, color.B); - Assert.Equal(alpha, color.A); - } - } - } - - private static void CopyFromZYXW(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - byte red = 1; - byte green = 2; - byte blue = 3; - byte alpha = 4; - - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYXW)) - { - row.Bytes[0] = blue; - row.Bytes[1] = green; - row.Bytes[2] = red; - row.Bytes[3] = alpha; - - pixels.CopyFrom(row, 0); - - Color color = (Color) (object) pixels[0, 0]; - Assert.Equal(red, color.R); - Assert.Equal(green, color.G); - Assert.Equal(blue, color.B); - Assert.Equal(alpha, color.A); - } - } - } - - private static void CopyToZYX(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - byte red = 1; - byte green = 2; - byte blue = 3; - - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYX)) - { - pixels[0, 0] = (TColor) (object) new Color(red, green, blue); - - pixels.CopyTo(row, 0); - - Assert.Equal(blue, row.Bytes[0]); - Assert.Equal(green, row.Bytes[1]); - Assert.Equal(red, row.Bytes[2]); - } - } - } - - private static void CopyToZYXW(Image image) - where TColor : struct, IPackedPixel - where TPacked : struct - { - using (PixelAccessor pixels = image.Lock()) - { - byte red = 1; - byte green = 2; - byte blue = 3; - byte alpha = 4; - - using (PixelRow row = new PixelRow(1, ComponentOrder.ZYXW)) - { - pixels[0, 0] = (TColor) (object) new Color(red, green, blue, alpha); - - pixels.CopyTo(row, 0); - - Assert.Equal(blue, row.Bytes[0]); - Assert.Equal(green, row.Bytes[1]); - Assert.Equal(red, row.Bytes[2]); - Assert.Equal(alpha, row.Bytes[3]); - } - } - } - } -} diff --git a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj b/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj deleted file mode 100644 index ab80f3d93..000000000 --- a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - Debug - AnyCPU - {635E0A15-3893-4763-A7F6-FCCFF85BCCA4} - Library - Properties - ImageSharp.Tests - ImageSharp.Tests - v4.6.1 - 512 - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - - - - - ..\..\packages\System.Numerics.Vectors.4.1.1\lib\net46\System.Numerics.Vectors.dll - True - - - - - - - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True - - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True - - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {fba0b5f6-09c2-4317-8ef6-6adb9b20e6b1} - ImageSharp46 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Numerics/PointTests.cs b/tests/ImageSharp.Tests46/Numerics/PointTests.cs deleted file mode 100644 index 82b26b946..000000000 --- a/tests/ImageSharp.Tests46/Numerics/PointTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the struct. - /// - public class PointTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - Point first = new Point(100, 100); - Point second = new Point(100, 100); - - Assert.Equal(first, second); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - Point first = new Point(0, 100); - Point second = new Point(100, 100); - - Assert.NotEqual(first, second); - } - - /// - /// Tests whether the point constructor correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - Point first = new Point(4, 5); - Assert.Equal(4, first.X); - Assert.Equal(5, first.Y); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Numerics/RationalTests.cs b/tests/ImageSharp.Tests46/Numerics/RationalTests.cs deleted file mode 100644 index 3d80b88fe..000000000 --- a/tests/ImageSharp.Tests46/Numerics/RationalTests.cs +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the struct. - /// - public class RationalTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - Rational r1 = new Rational(3, 2); - Rational r2 = new Rational(3, 2); - - Assert.Equal(r1, r2); - Assert.True(r1 == r2); - - Rational r3 = new Rational(7.55); - Rational r4 = new Rational(755, 100); - Rational r5 = new Rational(151, 20); - - Assert.Equal(r3, r4); - Assert.Equal(r4, r5); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - Rational first = new Rational(0, 100); - Rational second = new Rational(100, 100); - - Assert.NotEqual(first, second); - Assert.True(first != second); - } - - /// - /// Tests whether the Rational constructor correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - Rational rational = new Rational(7, 55); - Assert.Equal(7U, rational.Numerator); - Assert.Equal(55U, rational.Denominator); - - rational = new Rational(755, 100); - Assert.Equal(151U, rational.Numerator); - Assert.Equal(20U, rational.Denominator); - - rational = new Rational(755, 100, false); - Assert.Equal(755U, rational.Numerator); - Assert.Equal(100U, rational.Denominator); - - rational = new Rational(-7.55); - Assert.Equal(151U, rational.Numerator); - Assert.Equal(20U, rational.Denominator); - - rational = new Rational(7); - Assert.Equal(7U, rational.Numerator); - Assert.Equal(1U, rational.Denominator); - } - - [Fact] - public void Fraction() - { - Rational first = new Rational(1.0 / 1600); - Rational second = new Rational(1.0 / 1600, true); - Assert.False(first.Equals(second)); - } - - [Fact] - public void ToDouble() - { - Rational rational = new Rational(0, 0); - Assert.Equal(double.NaN, rational.ToDouble()); - - rational = new Rational(2, 0); - Assert.Equal(double.PositiveInfinity, rational.ToDouble()); - } - - [Fact] - public void ToStringRepresention() - { - Rational rational = new Rational(0, 0); - Assert.Equal("[ Indeterminate ]", rational.ToString()); - - rational = new Rational(double.PositiveInfinity); - Assert.Equal("[ PositiveInfinity ]", rational.ToString()); - - rational = new Rational(double.NegativeInfinity); - Assert.Equal("[ PositiveInfinity ]", rational.ToString()); - - rational = new Rational(0, 1); - Assert.Equal("0", rational.ToString()); - - rational = new Rational(2, 1); - Assert.Equal("2", rational.ToString()); - - rational = new Rational(1, 2); - Assert.Equal("1/2", rational.ToString()); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Numerics/RectangleTests.cs b/tests/ImageSharp.Tests46/Numerics/RectangleTests.cs deleted file mode 100644 index 2f9ad3d37..000000000 --- a/tests/ImageSharp.Tests46/Numerics/RectangleTests.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the struct. - /// - public class RectangleTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - Rectangle first = new Rectangle(1, 1, 100, 100); - Rectangle second = new Rectangle(1, 1, 100, 100); - - Assert.Equal(first, second); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - Rectangle first = new Rectangle(1, 1, 0, 100); - Rectangle second = new Rectangle(1, 1, 100, 100); - - Assert.NotEqual(first, second); - } - - /// - /// Tests whether the rectangle constructors correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - Rectangle first = new Rectangle(1, 1, 50, 100); - Assert.Equal(1, first.X); - Assert.Equal(1, first.Y); - Assert.Equal(50, first.Width); - Assert.Equal(100, first.Height); - Assert.Equal(1, first.Top); - Assert.Equal(51, first.Right); - Assert.Equal(101, first.Bottom); - Assert.Equal(1, first.Left); - - Rectangle second = new Rectangle(new Point(1, 1), new Size(50, 100)); - Assert.Equal(1, second.X); - Assert.Equal(1, second.Y); - Assert.Equal(50, second.Width); - Assert.Equal(100, second.Height); - Assert.Equal(1, second.Top); - Assert.Equal(51, second.Right); - Assert.Equal(101, second.Bottom); - Assert.Equal(1, second.Left); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Numerics/SignedRationalTests.cs b/tests/ImageSharp.Tests46/Numerics/SignedRationalTests.cs deleted file mode 100644 index cb7e21db0..000000000 --- a/tests/ImageSharp.Tests46/Numerics/SignedRationalTests.cs +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the struct. - /// - public class SignedRationalTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - SignedRational r1 = new SignedRational(3, 2); - SignedRational r2 = new SignedRational(3, 2); - - Assert.Equal(r1, r2); - Assert.True(r1 == r2); - - SignedRational r3 = new SignedRational(7.55); - SignedRational r4 = new SignedRational(755, 100); - SignedRational r5 = new SignedRational(151, 20); - - Assert.Equal(r3, r4); - Assert.Equal(r4, r5); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - SignedRational first = new SignedRational(0, 100); - SignedRational second = new SignedRational(100, 100); - - Assert.NotEqual(first, second); - Assert.True(first != second); - } - - /// - /// Tests whether the Rational constructor correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - SignedRational rational = new SignedRational(7, -55); - Assert.Equal(7, rational.Numerator); - Assert.Equal(-55, rational.Denominator); - - rational = new SignedRational(-755, 100); - Assert.Equal(-151, rational.Numerator); - Assert.Equal(20, rational.Denominator); - - rational = new SignedRational(-755, -100, false); - Assert.Equal(-755, rational.Numerator); - Assert.Equal(-100, rational.Denominator); - - rational = new SignedRational(-151, -20); - Assert.Equal(-151, rational.Numerator); - Assert.Equal(-20, rational.Denominator); - - rational = new SignedRational(-7.55); - Assert.Equal(-151, rational.Numerator); - Assert.Equal(20, rational.Denominator); - - rational = new SignedRational(7); - Assert.Equal(7, rational.Numerator); - Assert.Equal(1, rational.Denominator); - } - - [Fact] - public void Fraction() - { - SignedRational first = new SignedRational(1.0 / 1600); - SignedRational second = new SignedRational(1.0 / 1600, true); - Assert.False(first.Equals(second)); - } - - [Fact] - public void ToDouble() - { - SignedRational rational = new SignedRational(0, 0); - Assert.Equal(double.NaN, rational.ToDouble()); - - rational = new SignedRational(2, 0); - Assert.Equal(double.PositiveInfinity, rational.ToDouble()); - - rational = new SignedRational(-2, 0); - Assert.Equal(double.NegativeInfinity, rational.ToDouble()); - } - - [Fact] - public void ToStringRepresention() - { - SignedRational rational = new SignedRational(0, 0); - Assert.Equal("[ Indeterminate ]", rational.ToString()); - - rational = new SignedRational(double.PositiveInfinity); - Assert.Equal("[ PositiveInfinity ]", rational.ToString()); - - rational = new SignedRational(double.NegativeInfinity); - Assert.Equal("[ NegativeInfinity ]", rational.ToString()); - - rational = new SignedRational(0, 1); - Assert.Equal("0", rational.ToString()); - - rational = new SignedRational(2, 1); - Assert.Equal("2", rational.ToString()); - - rational = new SignedRational(1, 2); - Assert.Equal("1/2", rational.ToString()); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Numerics/SizeTests.cs b/tests/ImageSharp.Tests46/Numerics/SizeTests.cs deleted file mode 100644 index 29eb768d9..000000000 --- a/tests/ImageSharp.Tests46/Numerics/SizeTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - /// - /// Tests the struct. - /// - public class SizeTests - { - /// - /// Tests the equality operators for equality. - /// - [Fact] - public void AreEqual() - { - Size first = new Size(100, 100); - Size second = new Size(100, 100); - - Assert.Equal(first, second); - } - - /// - /// Tests the equality operators for inequality. - /// - [Fact] - public void AreNotEqual() - { - Size first = new Size(0, 100); - Size second = new Size(100, 100); - - Assert.NotEqual(first, second); - } - - /// - /// Tests whether the size constructor correctly assign properties. - /// - [Fact] - public void ConstructorAssignsProperties() - { - Size first = new Size(4, 5); - Assert.Equal(4, first.Width); - Assert.Equal(5, first.Height); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/AlphaTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/AlphaTest.cs deleted file mode 100644 index efbfe75a8..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/AlphaTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class AlphaTest : FileTestBase - { - public static readonly TheoryData AlphaValues - = new TheoryData - { - 20 , - 80 - }; - - [Theory] - [MemberData("AlphaValues")] - public void ImageShouldApplyAlphaFilter(int value) - { - string path = CreateOutputDirectory("Alpha"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Alpha(value) - .Save(output); - } - } - } - - [Theory] - [MemberData("AlphaValues")] - public void ImageShouldApplyAlphaFilterInBox(int value) - { - string path = CreateOutputDirectory("Alpha"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Alpha(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BackgroundColorTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/BackgroundColorTest.cs deleted file mode 100644 index a7ecf6c08..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BackgroundColorTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class BackgroundColorTest : FileTestBase - { - [Fact] - public void ImageShouldApplyBackgroundColorFilter() - { - string path = CreateOutputDirectory("BackgroundColor"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.BackgroundColor(Color.HotPink) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BinaryThreshold.cs b/tests/ImageSharp.Tests46/Processors/Filters/BinaryThreshold.cs deleted file mode 100644 index 10b174cd5..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BinaryThreshold.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class BinaryThresholdTest : FileTestBase - { - public static readonly TheoryData BinaryThresholdValues - = new TheoryData - { - .25f , - .75f , - }; - - [Theory] - [MemberData("BinaryThresholdValues")] - public void ImageShouldApplyBinaryThresholdFilter(float value) - { - string path = CreateOutputDirectory("BinaryThreshold"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BinaryThreshold(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BlackWhiteTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/BlackWhiteTest.cs deleted file mode 100644 index d4af4ad38..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BlackWhiteTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class BlackWhiteTest : FileTestBase - { - [Fact] - public void ImageShouldApplyBlackWhiteFilter() - { - string path = CreateOutputDirectory("BlackWhite"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.BlackWhite() - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BlendTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/BlendTest.cs deleted file mode 100644 index 653524e20..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BlendTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class BlendTest : FileTestBase - { - [Fact] - public void ImageShouldApplyBlendFilter() - { - string path = CreateOutputDirectory("Blend"); - - Image blend; - using (FileStream stream = File.OpenRead(TestImages.Bmp.Car)) - { - blend = new Image(stream); - } - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Blend(blend) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BoxBlurTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/BoxBlurTest.cs deleted file mode 100644 index 453d56863..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BoxBlurTest.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - - public class BoxBlurTest : FileTestBase - { - public static readonly TheoryData BoxBlurValues - = new TheoryData - { - 3 , - 5 , - }; - - [Theory] - [MemberData("BoxBlurValues")] - public void ImageShouldApplyBoxBlurFilter(int value) - { - string path = CreateOutputDirectory("BoxBlur"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BoxBlur(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/BrightnessTest.cs deleted file mode 100644 index e32c7d35e..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/BrightnessTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class BrightnessTest : FileTestBase - { - public static readonly TheoryData BrightnessValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData("BrightnessValues")] - public void ImageShouldApplyBrightnessFilter(int value) - { - string path = CreateOutputDirectory("Brightness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Brightness(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/ColorBlindnessTest.cs deleted file mode 100644 index 966514577..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/ColorBlindnessTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class ColorBlindnessTest : FileTestBase - { - public static readonly TheoryData ColorBlindnessFilters - = new TheoryData - { - ColorBlindness.Achromatomaly, - ColorBlindness.Achromatopsia, - ColorBlindness.Deuteranomaly, - ColorBlindness.Deuteranopia, - ColorBlindness.Protanomaly, - ColorBlindness.Protanopia, - ColorBlindness.Tritanomaly, - ColorBlindness.Tritanopia - }; - - [Theory] - [MemberData("ColorBlindnessFilters")] - public void ImageShouldApplyColorBlindnessFilter(ColorBlindness colorBlindness) - { - string path = CreateOutputDirectory("ColorBlindness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(colorBlindness); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.ColorBlindness(colorBlindness) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/ContrastTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/ContrastTest.cs deleted file mode 100644 index 3c83fd892..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/ContrastTest.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class ContrastTest : FileTestBase - { - public static readonly TheoryData ContrastValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData("ContrastValues")] - public void ImageShouldApplyContrastFilter(int value) - { - string path = CreateOutputDirectory("Contrast"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Contrast(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/GlowTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/GlowTest.cs deleted file mode 100644 index 1d317795d..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/GlowTest.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class GlowTest : FileTestBase - { - [Fact] - public void ImageShouldApplyGlowFilter() - { - string path = CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Glow() - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterColor() - { - string path = CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Color"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(Color.HotPink) - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterRadius() - { - string path = CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Radius"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(image.Width / 4) - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterInBox() - { - string path = CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/GrayscaleTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/GrayscaleTest.cs deleted file mode 100644 index 6796ba617..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/GrayscaleTest.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Processors; - using System.IO; - - using Xunit; - - public class GrayscaleTest : FileTestBase - { - public static readonly TheoryData GrayscaleValues - = new TheoryData - { - GrayscaleMode.Bt709 , - GrayscaleMode.Bt601 , - }; - - [Theory] - [MemberData("GrayscaleValues")] - public void ImageShouldApplyGrayscaleFilter(GrayscaleMode value) - { - string path = CreateOutputDirectory("Grayscale"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Grayscale(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/HueTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/HueTest.cs deleted file mode 100644 index a56aec9ec..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/HueTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class HueTest : FileTestBase - { - public static readonly TheoryData HueValues - = new TheoryData - { - 180 , - -180 , - }; - - [Theory] - [MemberData("HueValues")] - public void ImageShouldApplyHueFilter(int value) - { - string path = CreateOutputDirectory("Hue"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Hue(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/InvertTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/InvertTest.cs deleted file mode 100644 index 55bfa852b..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/InvertTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class InvertTest : FileTestBase - { - [Fact] - public void ImageShouldApplyInvertFilter() - { - string path = CreateOutputDirectory("Invert"); - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Invert() - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyInvertFilterInBox() - { - string path = CreateOutputDirectory("Invert"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Invert(new Rectangle(10, 10, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/KodachromeTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/KodachromeTest.cs deleted file mode 100644 index adb7cb36d..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/KodachromeTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class KodachromeTest : FileTestBase - { - [Fact] - public void ImageShouldApplyKodachromeFilter() - { - string path = CreateOutputDirectory("Kodachrome"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Kodachrome() - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/LomographTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/LomographTest.cs deleted file mode 100644 index 79a7aa3ba..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/LomographTest.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class LomographTest : FileTestBase - { - [Fact] - public void ImageShouldApplyLomographFilter() - { - string path = CreateOutputDirectory("Lomograph"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Lomograph() - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyLomographFilterInBox() - { - string path = CreateOutputDirectory("Lomograph"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Lomograph(new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/PolaroidTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/PolaroidTest.cs deleted file mode 100644 index dc9d3a150..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/PolaroidTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class PolaroidTest : FileTestBase - { - [Fact] - public void ImageShouldApplyPolaroidFilter() - { - string path = CreateOutputDirectory("Polaroid"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Polaroid() - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/SaturationTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/SaturationTest.cs deleted file mode 100644 index 5fe4c3e00..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/SaturationTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class SaturationTest : FileTestBase - { - public static readonly TheoryData SaturationValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData("SaturationValues")] - public void ImageShouldApplySaturationFilter(int value) - { - string path = CreateOutputDirectory("Saturation"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Saturation(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/SepiaTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/SepiaTest.cs deleted file mode 100644 index b5e4d3105..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/SepiaTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class SepiaTest : FileTestBase - { - [Fact] - public void ImageShouldApplySepiaFilter() - { - string path = CreateOutputDirectory("Sepia"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Sepia() - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Filters/VignetteTest.cs b/tests/ImageSharp.Tests46/Processors/Filters/VignetteTest.cs deleted file mode 100644 index 3fddad1da..000000000 --- a/tests/ImageSharp.Tests46/Processors/Filters/VignetteTest.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class VignetteTest : FileTestBase - { - [Fact] - public void ImageShouldApplyVignetteFilter() - { - string path = CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Vignette() - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterColor() - { - string path = CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Color"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(Color.HotPink) - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterRadius() - { - string path = CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Radius"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(image.Width / 4, image.Height / 4) - .Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterInBox() - { - string path = CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/AutoOrientTests.cs b/tests/ImageSharp.Tests46/Processors/Samplers/AutoOrientTests.cs deleted file mode 100644 index 97cd71718..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/AutoOrientTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - using Xunit; - - public class AutoOrientTests : FileTestBase - { - public static readonly TheoryData OrientationValues - = new TheoryData - { - { RotateType.None, FlipType.None, 0 }, - { RotateType.None, FlipType.None, 1 }, - { RotateType.None, FlipType.Horizontal, 2 }, - { RotateType.Rotate180, FlipType.None, 3 }, - { RotateType.Rotate180, FlipType.Horizontal, 4 }, - { RotateType.Rotate90, FlipType.Horizontal, 5 }, - { RotateType.Rotate270, FlipType.None, 6 }, - { RotateType.Rotate90, FlipType.Vertical, 7 }, - { RotateType.Rotate90, FlipType.None, 8 }, - }; - - [Theory] - [MemberData("OrientationValues")] - public void ImageShouldFlip(RotateType rotateType, FlipType flipType, ushort orientation) - { - string path = CreateOutputDirectory("AutoOrient"); - - string file = TestImages.Bmp.F; - - using (FileStream stream = File.OpenRead(file)) - { - string filename = Path.GetFileNameWithoutExtension(file) + "-" + orientation + Path.GetExtension(file); - - Image image = new Image(stream); - image.ExifProfile = new ExifProfile(); - image.ExifProfile.SetValue(ExifTag.Orientation, orientation); - - using (FileStream before = File.OpenWrite($"{path}/before-{filename}")) - { - using (FileStream after = File.OpenWrite($"{path}/after-{filename}")) - { - image.RotateFlip(rotateType, flipType) - .Save(before) - .AutoOrient() - .Save(after); - } - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/CropTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/CropTest.cs deleted file mode 100644 index 9e9dd34db..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/CropTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class CropTest : FileTestBase - { - [Fact] - public void ImageShouldApplyCropSampler() - { - string path = CreateOutputDirectory("Crop"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Crop(image.Width / 2, image.Height / 2) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/DetectEdgesTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/DetectEdgesTest.cs deleted file mode 100644 index ce088eac4..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/DetectEdgesTest.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class DetectEdgesTest : FileTestBase - { - public static readonly TheoryData DetectEdgesFilters - = new TheoryData - { - EdgeDetection.Kayyali, - EdgeDetection.Kirsch, - EdgeDetection.Lapacian3X3, - EdgeDetection.Lapacian5X5, - EdgeDetection.LaplacianOfGaussian, - EdgeDetection.Prewitt, - EdgeDetection.RobertsCross, - EdgeDetection.Robinson, - EdgeDetection.Scharr, - EdgeDetection.Sobel, - }; - - [Theory] - [MemberData(nameof(DetectEdgesFilters))] - public void ImageShouldApplyDetectEdgesFilter(EdgeDetection detector) - { - string path = CreateOutputDirectory("DetectEdges"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(detector); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.DetectEdges(detector) - .Save(output); - } - } - } - - [Theory] - [MemberData("DetectEdgesFilters")] - public void ImageShouldApplyDetectEdgesFilterInBox(EdgeDetection detector) - { - string path = CreateOutputDirectory("DetectEdges"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(detector + "-InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/EntropyCropTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/EntropyCropTest.cs deleted file mode 100644 index fdbbc5cde..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/EntropyCropTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class EntropyCropTest : FileTestBase - { - public static readonly TheoryData EntropyCropValues - = new TheoryData - { - .25f , - .75f , - }; - - [Theory] - [MemberData("EntropyCropValues")] - public void ImageShouldApplyEntropyCropSampler(float value) - { - string path = CreateOutputDirectory("EntropyCrop"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.EntropyCrop(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/FlipTests.cs b/tests/ImageSharp.Tests46/Processors/Samplers/FlipTests.cs deleted file mode 100644 index c07071e70..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/FlipTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class FlipTests : FileTestBase - { - public static readonly TheoryData FlipValues - = new TheoryData - { - { FlipType.None }, - { FlipType.Vertical }, - { FlipType.Horizontal }, - }; - - [Theory] - [MemberData("FlipValues")] - public void ImageShouldFlip(FlipType flipType) - { - string path = CreateOutputDirectory("Flip"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(flipType); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Flip(flipType) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/GuassianBlurTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/GuassianBlurTest.cs deleted file mode 100644 index cd1cc5638..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/GuassianBlurTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class GuassianBlurTest : FileTestBase - { - public static readonly TheoryData GuassianBlurValues - = new TheoryData - { - 3 , - 5 , - }; - - [Theory] - [MemberData("GuassianBlurValues")] - public void ImageShouldApplyGuassianBlurFilter(int value) - { - string path = CreateOutputDirectory("GuassianBlur"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.GuassianBlur(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/GuassianSharpenTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/GuassianSharpenTest.cs deleted file mode 100644 index 5672b5bae..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/GuassianSharpenTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class GuassianSharpenTest : FileTestBase - { - public static readonly TheoryData GuassianSharpenValues - = new TheoryData - { - 3 , - 5 , - }; - - [Theory] - [MemberData("GuassianSharpenValues")] - public void ImageShouldApplyGuassianSharpenFilter(int value) - { - string path = CreateOutputDirectory("GuassianSharpen"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.GuassianSharpen(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/OilPaintTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/OilPaintTest.cs deleted file mode 100644 index 8b5ff3f51..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/OilPaintTest.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.IO; - - using Xunit; - - public class OilPaintTest : FileTestBase - { - public static readonly TheoryData> OilPaintValues - = new TheoryData> - { - new Tuple(15,10), - new Tuple(6,5) - }; - - [Theory] - [MemberData(nameof(OilPaintValues))] - public void ImageShouldApplyOilPaintFilter(Tuple value) - { - string path = CreateOutputDirectory("OilPaint"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.OilPaint(value.Item1, value.Item2) - .Save(output); - } - } - } - - [Theory] - [MemberData(nameof(OilPaintValues))] - public void ImageShouldApplyOilPaintFilterInBox(Tuple value) - { - string path = CreateOutputDirectory("OilPaint"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.OilPaint(value.Item1, value.Item2, new Rectangle(10, 10, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/PadTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/PadTest.cs deleted file mode 100644 index 5a33aac2b..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/PadTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class PadTest : FileTestBase - { - [Fact] - public void ImageShouldApplyPadSampler() - { - string path = CreateOutputDirectory("Pad"); - - foreach (TestFile file in Files) - { - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Pad(image.Width + 50, image.Height + 50) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/PixelateTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/PixelateTest.cs deleted file mode 100644 index 397bdef06..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/PixelateTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class PixelateTest : FileTestBase - { - public static readonly TheoryData PixelateValues - = new TheoryData - { - 4 , - 8 - }; - - [Theory] - [MemberData(nameof(PixelateValues))] - public void ImageShouldApplyPixelateFilter(int value) - { - string path = CreateOutputDirectory("Pixelate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Pixelate(value) - .Save(output); - } - } - } - - [Theory] - [MemberData(nameof(PixelateValues))] - public void ImageShouldApplyPixelateFilterInBox(int value) - { - string path = CreateOutputDirectory("Pixelate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Pixelate(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/ResizeTests.cs b/tests/ImageSharp.Tests46/Processors/Samplers/ResizeTests.cs deleted file mode 100644 index 876ba7ebc..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/ResizeTests.cs +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class ResizeTests : FileTestBase - { - public static readonly TheoryData ReSamplers = - new TheoryData - { - { "Bicubic", new BicubicResampler() }, - { "Triangle", new TriangleResampler() }, - { "NearestNeighbor", new NearestNeighborResampler() }, - // Perf: Enable for local testing only - //{ "Box", new BoxResampler() }, - //{ "Lanczos3", new Lanczos3Resampler() }, - //{ "Lanczos5", new Lanczos5Resampler() }, - //{ "Lanczos8", new Lanczos8Resampler() }, - { "MitchellNetravali", new MitchellNetravaliResampler() }, - //{ "Hermite", new HermiteResampler() }, - //{ "Spline", new SplineResampler() }, - //{ "Robidoux", new RobidouxResampler() }, - //{ "RobidouxSharp", new RobidouxSharpResampler() }, - //{ "RobidouxSoft", new RobidouxSoftResampler() }, - //{ "Welch", new WelchResampler() } - }; - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResize(string name, IResampler sampler) - { - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(image.Width / 2, image.Height / 2, sampler, true) - //image.Resize(555, 275, sampler, false) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWidthAndKeepAspect(string name, IResampler sampler) - { - name = name + "-FixedWidth"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(image.Width / 3, 0, sampler, false) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeHeightAndKeepAspect(string name, IResampler sampler) - { - name = name + "-FixedHeight"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(0, image.Height / 3, sampler, false) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithCropWidthMode(string name, IResampler sampler) - { - name = name + "-CropWidth"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(image.Width / 2, image.Height) - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithCropHeightMode(string name, IResampler sampler) - { - name = name + "-CropHeight"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(image.Width, image.Height / 2) - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithPadMode(string name, IResampler sampler) - { - name = name + "-Pad"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Size = new Size(image.Width + 200, image.Height), - Mode = ResizeMode.Pad - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithBoxPadMode(string name, IResampler sampler) - { - name = name + "-BoxPad"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(image.Width + 200, image.Height + 200), - Mode = ResizeMode.BoxPad - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithMaxMode(string name, IResampler sampler) - { - name = name + "Max"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(300, 300), - Mode = ResizeMode.Max - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithMinMode(string name, IResampler sampler) - { - name = name + "-Min"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(image.Width - 50, image.Height - 25), - Mode = ResizeMode.Min - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [MemberData("ReSamplers")] - public void ImageShouldResizeWithStretchMode(string name, IResampler sampler) - { - name = name + "Stretch"; - - string path = CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions() - { - Sampler = sampler, - Size = new Size(image.Width - 200, image.Height), - Mode = ResizeMode.Stretch - }; - - image.Resize(options) - .Save(output); - } - } - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - [InlineData(2, 0)] - public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) - { - Lanczos3Resampler sampler = new Lanczos3Resampler(); - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/RotateFlipTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/RotateFlipTest.cs deleted file mode 100644 index 04704b672..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/RotateFlipTest.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class RotateFlipTest : FileTestBase - { - public static readonly TheoryData RotateFlipValues - = new TheoryData - { - { RotateType.None, FlipType.Vertical }, - { RotateType.None, FlipType.Horizontal }, - { RotateType.Rotate90, FlipType.None }, - { RotateType.Rotate180, FlipType.None }, - { RotateType.Rotate270, FlipType.None }, - }; - - [Theory] - [MemberData("RotateFlipValues")] - public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType) - { - string path = CreateOutputDirectory("RotateFlip"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(rotateType + "-" + flipType); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.RotateFlip(rotateType, flipType) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/RotateTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/RotateTest.cs deleted file mode 100644 index 96fb39e07..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/RotateTest.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class RotateTest : FileTestBase - { - public static readonly TheoryData RotateFloatValues - = new TheoryData - { - 170 , - -170 , - }; - - public static readonly TheoryData RotateEnumValues - = new TheoryData - { - RotateType.None, - RotateType.Rotate90, - RotateType.Rotate180, - RotateType.Rotate270 - }; - - [Theory] - [MemberData("RotateFloatValues")] - public void ImageShouldApplyRotateSampler(float value) - { - string path = CreateOutputDirectory("Rotate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Rotate(value) - .Save(output); - } - } - } - - [Theory] - [MemberData("RotateEnumValues")] - public void ImageShouldApplyRotateSampler(RotateType value) - { - string path = CreateOutputDirectory("Rotate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Rotate(value) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Processors/Samplers/SkewTest.cs b/tests/ImageSharp.Tests46/Processors/Samplers/SkewTest.cs deleted file mode 100644 index 11db7e691..000000000 --- a/tests/ImageSharp.Tests46/Processors/Samplers/SkewTest.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using Xunit; - - public class SkewTest : FileTestBase - { - public static readonly TheoryData SkewValues - = new TheoryData - { - { 20, 10 }, - { -20, -10 } - }; - - [Theory] - [MemberData("SkewValues")] - public void ImageShouldApplySkewSampler(float x, float y) - { - string path = CreateOutputDirectory("Skew"); - - // Matches live example - // http://www.w3schools.com/css/tryit.asp?filename=trycss3_transform_skew - foreach (TestFile file in Files) - { - string filename = file.GetFileName(x + "-" + y); - Image image = file.CreateImage(); - - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Skew(x, y) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests46/Profiles/Exif/ExifProfileTests.cs deleted file mode 100644 index fa7347a97..000000000 --- a/tests/ImageSharp.Tests46/Profiles/Exif/ExifProfileTests.cs +++ /dev/null @@ -1,325 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.Collections; - using System.IO; - using System.Linq; - using System.Text; - using Xunit; - - public class ExifProfileTests - { - [Fact] - public void Constructor() - { - using (FileStream stream = File.OpenRead(TestImages.Jpeg.Calliphora)) - { - Image image = new Image(stream); - - Assert.Null(image.ExifProfile); - - image.ExifProfile = new ExifProfile(); - image.ExifProfile.SetValue(ExifTag.Copyright, "Dirk Lemstra"); - - image = WriteAndRead(image); - - Assert.NotNull(image.ExifProfile); - Assert.Equal(1, image.ExifProfile.Values.Count()); - - ExifValue value = image.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright); - TestValue(value, "Dirk Lemstra"); - } - } - - [Fact] - public void ConstructorEmpty() - { - new ExifProfile((byte[])null); - new ExifProfile(new byte[] { }); - } - - [Fact] - public void ConstructorCopy() - { - Assert.Throws(() => { new ExifProfile((ExifProfile)null); }); - - ExifProfile profile = GetExifProfile(); - - ExifProfile clone = new ExifProfile(profile); - TestProfile(clone); - - profile.SetValue(ExifTag.ColorSpace, (ushort)2); - - clone = new ExifProfile(profile); - TestProfile(clone); - } - - [Fact] - public void WriteFraction() - { - using (MemoryStream memStream = new MemoryStream()) - { - double exposureTime = 1.0 / 1600; - - ExifProfile profile = GetExifProfile(); - - profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime)); - - Image image = new Image(1, 1); - image.ExifProfile = profile; - - image.SaveAsJpeg(memStream); - - memStream.Position = 0; - image = new Image(memStream); - - profile = image.ExifProfile; - Assert.NotNull(profile); - - ExifValue value = profile.GetValue(ExifTag.ExposureTime); - Assert.NotNull(value); - Assert.NotEqual(exposureTime, ((Rational)value.Value).ToDouble()); - - memStream.Position = 0; - profile = GetExifProfile(); - - profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true)); - image.ExifProfile = profile; - - image.SaveAsJpeg(memStream); - - memStream.Position = 0; - image = new Image(memStream); - - profile = image.ExifProfile; - Assert.NotNull(profile); - - value = profile.GetValue(ExifTag.ExposureTime); - Assert.Equal(exposureTime, ((Rational)value.Value).ToDouble()); - } - } - - [Fact] - public void ReadWriteInfinity() - { - using (FileStream stream = File.OpenRead(TestImages.Jpeg.Floorplan)) - { - Image image = new Image(stream); - image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity)); - - image = WriteAndRead(image); - ExifValue value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue); - Assert.NotNull(value); - Assert.Equal(new SignedRational(double.PositiveInfinity), value.Value); - - image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity)); - - image = WriteAndRead(image); - value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue); - Assert.NotNull(value); - Assert.Equal(new SignedRational(double.NegativeInfinity), value.Value); - - image.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity)); - - image = WriteAndRead(image); - value = image.ExifProfile.GetValue(ExifTag.FlashEnergy); - Assert.NotNull(value); - Assert.Equal(new Rational(double.PositiveInfinity), value.Value); - } - } - - [Fact] - public void SetValue() - { - Rational[] latitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) }; - - using (FileStream stream = File.OpenRead(TestImages.Jpeg.Floorplan)) - { - Image image = new Image(stream); - image.ExifProfile.SetValue(ExifTag.Software, "ImageSharp"); - - ExifValue value = image.ExifProfile.GetValue(ExifTag.Software); - TestValue(value, "ImageSharp"); - - Assert.Throws(() => { value.Value = 15; }); - - image.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55)); - - value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); - - TestValue(value, new SignedRational(7555, 100)); - - Assert.Throws(() => { value.Value = 75; }); - - image.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0)); - - value = image.ExifProfile.GetValue(ExifTag.XResolution); - TestValue(value, new Rational(150, 1)); - - Assert.Throws(() => { value.Value = "ImageSharp"; }); - - image.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null); - - value = image.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); - TestValue(value, (string)null); - - image.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude); - - value = image.ExifProfile.GetValue(ExifTag.GPSLatitude); - TestValue(value, latitude); - - image = WriteAndRead(image); - - Assert.NotNull(image.ExifProfile); - Assert.Equal(17, image.ExifProfile.Values.Count()); - - value = image.ExifProfile.GetValue(ExifTag.Software); - TestValue(value, "ImageSharp"); - - value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); - TestValue(value, new SignedRational(75.55)); - - value = image.ExifProfile.GetValue(ExifTag.XResolution); - TestValue(value, new Rational(150.0)); - - value = image.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); - Assert.Null(value); - - value = image.ExifProfile.GetValue(ExifTag.GPSLatitude); - TestValue(value, latitude); - - image.ExifProfile.Parts = ExifParts.ExifTags; - - image = WriteAndRead(image); - - Assert.NotNull(image.ExifProfile); - Assert.Equal(8, image.ExifProfile.Values.Count()); - - Assert.NotNull(image.ExifProfile.GetValue(ExifTag.ColorSpace)); - Assert.True(image.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.False(image.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.Null(image.ExifProfile.GetValue(ExifTag.ColorSpace)); - - Assert.Equal(7, image.ExifProfile.Values.Count()); - } - } - - [Fact] - public void Values() - { - ExifProfile profile = GetExifProfile(); - - TestProfile(profile); - - var thumbnail = profile.CreateThumbnail(); - Assert.NotNull(thumbnail); - Assert.Equal(256, thumbnail.Width); - Assert.Equal(170, thumbnail.Height); - } - - [Fact] - public void WriteTooLargeProfile() - { - StringBuilder junk = new StringBuilder(); - for (int i = 0; i < 65500; i++) - junk.Append("I"); - - Image image = new Image(100, 100); - image.ExifProfile = new ExifProfile(); - image.ExifProfile.SetValue(ExifTag.ImageDescription, junk.ToString()); - - using (MemoryStream memStream = new MemoryStream()) - { - Assert.Throws(() => image.SaveAsJpeg(memStream)); - } - } - - private static ExifProfile GetExifProfile() - { - using (FileStream stream = File.OpenRead(TestImages.Jpeg.Floorplan)) - { - Image image = new Image(stream); - - ExifProfile profile = image.ExifProfile; - Assert.NotNull(profile); - - return profile; - } - } - - private static Image WriteAndRead(Image image) - { - using (MemoryStream memStream = new MemoryStream()) - { - image.SaveAsJpeg(memStream); - - memStream.Position = 0; - return new Image(memStream); - } - } - - private static void TestProfile(ExifProfile profile) - { - Assert.NotNull(profile); - - Assert.Equal(16, profile.Values.Count()); - - foreach (ExifValue value in profile.Values) - { - Assert.NotNull(value.Value); - - if (value.Tag == ExifTag.Software) - Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.ToString()); - - if (value.Tag == ExifTag.XResolution) - Assert.Equal(new Rational(300.0), value.Value); - - if (value.Tag == ExifTag.PixelXDimension) - Assert.Equal(2338U, value.Value); - } - } - - private static void TestValue(ExifValue value, string expected) - { - Assert.NotNull(value); - Assert.Equal(expected, value.Value); - } - - private static void TestValue(ExifValue value, Rational expected) - { - Assert.NotNull(value); - Assert.Equal(expected, value.Value); - } - - private static void TestValue(ExifValue value, SignedRational expected) - { - Assert.NotNull(value); - Assert.Equal(expected, value.Value); - } - - private static void TestValue(ExifValue value, Rational[] expected) - { - Assert.NotNull(value); - - Assert.Equal(expected, (ICollection)value.Value); - } - - private static void TestValue(ExifValue value, double expected) - { - Assert.NotNull(value); - Assert.Equal(expected, value.Value); - } - - private static void TestValue(ExifValue value, double[] expected) - { - Assert.NotNull(value); - - Assert.Equal(expected, (ICollection)value.Value); - } - } -} diff --git a/tests/ImageSharp.Tests46/Profiles/Exif/ExifTagDescriptionAttributeTests.cs b/tests/ImageSharp.Tests46/Profiles/Exif/ExifTagDescriptionAttributeTests.cs deleted file mode 100644 index 4f77dc11a..000000000 --- a/tests/ImageSharp.Tests46/Profiles/Exif/ExifTagDescriptionAttributeTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using Xunit; - - public class ExifDescriptionAttributeTests - { - [Fact] - public void Test_ExifTag() - { - var exifProfile = new ExifProfile(); - - exifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)1); - ExifValue value = exifProfile.GetValue(ExifTag.ResolutionUnit); - Assert.Equal("None", value.ToString()); - - exifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)2); - value = exifProfile.GetValue(ExifTag.ResolutionUnit); - Assert.Equal("Inches", value.ToString()); - - exifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)3); - value = exifProfile.GetValue(ExifTag.ResolutionUnit); - Assert.Equal("Centimeter", value.ToString()); - - exifProfile.SetValue(ExifTag.ResolutionUnit, (ushort)4); - value = exifProfile.GetValue(ExifTag.ResolutionUnit); - Assert.Equal("4", value.ToString()); - - exifProfile.SetValue(ExifTag.ImageWidth, 123); - value = exifProfile.GetValue(ExifTag.ImageWidth); - Assert.Equal("123", value.ToString()); - } - } -} diff --git a/tests/ImageSharp.Tests46/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests46/Profiles/Exif/ExifValueTests.cs deleted file mode 100644 index e79cb7186..000000000 --- a/tests/ImageSharp.Tests46/Profiles/Exif/ExifValueTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - using System.Linq; - using Xunit; - - public class ExifValueTests - { - private static ExifValue GetExifValue() - { - using (FileStream stream = File.OpenRead(TestImages.Jpeg.Floorplan)) - { - Image image = new Image(stream); - - ExifProfile profile = image.ExifProfile; - Assert.NotNull(profile); - - return profile.Values.First(); - } - } - - [Fact] - public void IEquatable() - { - ExifValue first = GetExifValue(); - ExifValue second = GetExifValue(); - - Assert.True(first == second); - Assert.True(first.Equals(second)); - Assert.True(first.Equals((object)second)); - } - - [Fact] - public void Properties() - { - ExifValue value = GetExifValue(); - - Assert.Equal(ExifDataType.Ascii, value.DataType); - Assert.Equal(ExifTag.GPSDOP, value.Tag); - Assert.Equal(false, value.IsArray); - Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.ToString()); - Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.Value); - } - } -} diff --git a/tests/ImageSharp.Tests46/Properties/AssemblyInfo.cs b/tests/ImageSharp.Tests46/Properties/AssemblyInfo.cs deleted file mode 100644 index 3d57ceff5..000000000 --- a/tests/ImageSharp.Tests46/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ImageSharp.Tests")] -[assembly: AssemblyDescription("A cross-platform library for processing of image files written in C#")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ImageSharp.Tests")] -[assembly: AssemblyCopyright("Copyright © James Jackson-South and contributors.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f836e8e6-b4d9-4208-8346-140c74678b91")] diff --git a/tests/ImageSharp.Tests46/TestFile.cs b/tests/ImageSharp.Tests46/TestFile.cs deleted file mode 100644 index f7e7f8517..000000000 --- a/tests/ImageSharp.Tests46/TestFile.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.IO; - -namespace ImageSharp.Tests -{ - public class TestFile - { - private readonly Image image; - private readonly string file; - - public TestFile(string file) - { - this.file = file; - - using (FileStream stream = File.OpenRead(file)) - { - this.image = new Image(stream); - } - } - - public string FileName - { - get - { - return Path.GetFileName(this.file); - } - } - - public string FileNameWithoutExtension - { - get - { - return Path.GetFileNameWithoutExtension(this.file); - } - } - - public string GetFileName(object value) - { - return this.FileNameWithoutExtension + "-" + value + Path.GetExtension(this.file); - } - - public string GetFileNameWithoutExtension(object value) - { - return this.FileNameWithoutExtension + "-" + value; - } - - public Image CreateImage() - { - return new Image(this.image); - } - } -} diff --git a/tests/ImageSharp.Tests46/TestImages.cs b/tests/ImageSharp.Tests46/TestImages.cs deleted file mode 100644 index edb2449e8..000000000 --- a/tests/ImageSharp.Tests46/TestImages.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -using System.Diagnostics.PerformanceData; - -namespace ImageSharp.Tests -{ - /// - /// Class that contains all the test images. - /// - public static class TestImages - { - public static class Png - { - private static readonly string folder = "../../TestImages/Formats/Png/"; - - public static string P1 => folder + "pl.png"; - public static string Pd => folder + "pd.png"; - public static string Blur => folder + "blur.png"; - public static string Indexed => folder + "indexed.png"; - public static string Splash => folder + "splash.png"; - } - - public static class Jpeg - { - private const string Folder = "../../TestImages/Formats/Jpg/"; - public const string Cmyk = Folder + "cmyk.jpg"; - public const string Exif = Folder + "exif.jpg"; - public const string Floorplan = Folder + "Floorplan.jpeg"; - public const string Calliphora = Folder + "Calliphora.jpg"; - public const string Turtle = Folder + "turtle.jpg"; - public const string Fb = Folder + "fb.jpg"; - public const string Progress = Folder + "progress.jpg"; - public const string GammaDalaiLamaGray = Folder + "gamma_dalai_lama_gray.jpg"; - - public const string Geneserath = Folder + "geneserath.jpg"; - - public static readonly string[] All = new[] - { - Cmyk, Exif, Floorplan, Calliphora, Turtle, Fb, Progress, GammaDalaiLamaGray, Geneserath - }; - } - - public static class Bmp - { - private static readonly string folder = "../../TestImages/Formats/Bmp/"; - - public static string Car => folder + "Car.bmp"; - public static string F => folder + "F.bmp"; - public static string NegHeight => folder + "neg_height.bmp"; - - public static string[] All => new[] {Car, F, NegHeight}; - } - - public static class Gif - { - private static readonly string folder = "../../TestImages/Formats/Gif/"; - - public static string Rings => folder + "rings.gif"; - public static string Giphy => folder + "giphy.gif"; - } - } -} diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/Car.bmp b/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/Car.bmp deleted file mode 100644 index edaf3a8e4..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/Car.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d3a4a30cd67db6ded1e57126c7ba275404703e64b3dfb1c9c711128c15b0124 -size 810054 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/F.bmp b/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/F.bmp deleted file mode 100644 index d95598bef..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/F.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6da008d2b285b2db946e6d4ebf8569b0ddd4a05ef273b38304cb65afccac87b3 -size 65502 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/neg_height.bmp b/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/neg_height.bmp deleted file mode 100644 index d0b99a902..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Bmp/neg_height.bmp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81437b88a5d92fcb545fae4991643a0c73d95d0277dac0b79074971780008c8c -size 6220854 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Gif/giphy.gif b/tests/ImageSharp.Tests46/TestImages/Formats/Gif/giphy.gif deleted file mode 100644 index 029afdec6..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Gif/giphy.gif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3f42abd9f3e493a0acd5303ab0d37a6179835c5a14364a1f001abd9d9e906f96 -size 53655 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Gif/rings.gif b/tests/ImageSharp.Tests46/TestImages/Formats/Gif/rings.gif deleted file mode 100644 index acd5d6339..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Gif/rings.gif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:716448da88152225767c024aac498f5b7562b6e8391907cefc9d03dba40050fd -size 53435 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Calliphora.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Calliphora.jpg deleted file mode 100644 index aa3fdef01..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Calliphora.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:67172fcab405f914587b88cd1106328e6b24ab59d622ba509dcc99509951ff5c -size 254766 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Floorplan.jpeg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Floorplan.jpeg deleted file mode 100644 index 6f439d220..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/Floorplan.jpeg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:de00b34b78dfa0886c93d8dd5cede27b4940d5c620e44631e77e6dc8838befc3 -size 161577 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/cmyk.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/cmyk.jpg deleted file mode 100644 index 2fe8f0a61..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/cmyk.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:33e3546a64df7fa1d528441926421b193e399a83490a6307762fb7eee9640bf0 -size 611572 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/exif.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/exif.jpg deleted file mode 100644 index cba862660..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/exif.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a9d04b92d0de5836c59ede8ae421235488e4031e893e07b1fe7e4b78f6a9901 -size 32764 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/fb.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/fb.jpg deleted file mode 100644 index 7241890e2..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/fb.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:93bb4d6281dc1e845db57e836e0dca30b7a4062e81044efb27ad4d8b1a33130c -size 15787 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg deleted file mode 100644 index c305caef4..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d92a88b04518e266b98d9d2f5b4eb88f3f91c332d3397ea859bab8cabc41185 -size 84887 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/geneserath.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/geneserath.jpg deleted file mode 100644 index af0c04a1c..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/geneserath.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c71e5b1ba181a5b17ba9814c2025650de592efabf4062bd77baa3c8e774df007 -size 223841 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/progress.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/progress.jpg deleted file mode 100644 index 30b214c22..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/progress.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a9a1f0da3c5b3a3e7e7f35abe9f5b458163b48ca56226227b3d3cffe06af1971 -size 44884 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/turtle.jpg b/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/turtle.jpg deleted file mode 100644 index 07d96543b..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Jpg/turtle.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e5c576b0c5e743cfd498b110305268ecbae63c62061ba6c7eb8e060728191f1 -size 55126 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Png/blur.png b/tests/ImageSharp.Tests46/TestImages/Formats/Png/blur.png deleted file mode 100644 index 2ac488b7c..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Png/blur.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:10df946d3d6a9832bacd9ac2587b890c348d17731412c8fd17c34f66f35d9c94 -size 183768 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Png/indexed.png b/tests/ImageSharp.Tests46/TestImages/Formats/Png/indexed.png deleted file mode 100644 index f06e1cbd6..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Png/indexed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65566cde707c02757a26fb5fb7702be9c53f55c17a1748d81c384559de2d1173 -size 33529 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Png/pd.png b/tests/ImageSharp.Tests46/TestImages/Formats/Png/pd.png deleted file mode 100644 index 12fde3229..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Png/pd.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:91dd938fb916d368738826741551aea694b340ba3362f56200c5d3c5e5510267 -size 1406 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Png/pl.png b/tests/ImageSharp.Tests46/TestImages/Formats/Png/pl.png deleted file mode 100644 index 15e991284..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Png/pl.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa550e61fe276d2ebee8666d0cbb811449433edb76e01bcd38cb00c1aafc417e -size 91 diff --git a/tests/ImageSharp.Tests46/TestImages/Formats/Png/splash.png b/tests/ImageSharp.Tests46/TestImages/Formats/Png/splash.png deleted file mode 100644 index ca4f86bce..000000000 --- a/tests/ImageSharp.Tests46/TestImages/Formats/Png/splash.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4c13422913f1c1910f8dd607236e79b4a5c7053deb8ce1c8be8372eca7465fb -size 245033 diff --git a/tests/ImageSharp.Tests46/app.config b/tests/ImageSharp.Tests46/app.config deleted file mode 100644 index 5e95024db..000000000 --- a/tests/ImageSharp.Tests46/app.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/packages.config b/tests/ImageSharp.Tests46/packages.config deleted file mode 100644 index e96e29cd6..000000000 --- a/tests/ImageSharp.Tests46/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file