From a2ec1129fb3eab8f1bba3dc11a7cac92e5b158da Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 30 Jul 2016 21:38:36 +1000 Subject: [PATCH] Delete old code. Former-commit-id: c1c2d867171de871262331e5db1e55f0fe462312 Former-commit-id: 41d014fd7ba8e3a7f8a84d40d368eb330baab3c5 Former-commit-id: 78ac6e4c0afaeefd95f3604bf778584b48c3cadd --- src/ImageProcessorCore - Copy/Bootstrapper.cs | 124 --- src/ImageProcessorCore - Copy/Colors/Color.cs | 518 ------------ .../Colors/ColorConstants.cs | 179 ---- .../Colors/ColorDefinitions.cs | 728 ---------------- .../Colors/ColorTransforms.cs | 73 -- .../Colors/ColorspaceTransforms.cs | 285 ------- .../Colors/Colorspaces/Bgra32.cs | 168 ---- .../Colors/Colorspaces/CieLab.cs | 193 ----- .../Colors/Colorspaces/CieXyz.cs | 184 ---- .../Colors/Colorspaces/Cmyk.cs | 197 ----- .../Colors/Colorspaces/Hsl.cs | 213 ----- .../Colors/Colorspaces/Hsv.cs | 207 ----- .../Colors/Colorspaces/YCbCr.cs | 183 ---- .../Colors/IAlmostEquatable.cs | 29 - .../Colors/RgbaComponent.cs | 33 - .../Common/Exceptions/ImageFormatException.cs | 45 - .../Exceptions/ImageProcessingException.cs | 44 - .../Common/Extensions/ByteExtensions.cs | 60 -- .../Common/Extensions/ComparableExtensions.cs | 145 ---- .../Common/Extensions/EnumerableExtensions.cs | 88 -- .../Common/Helpers/Guard.cs | 192 ----- .../Common/Helpers/ImageMaths.cs | 289 ------- .../Filters/Alpha.cs | 52 -- .../Filters/BackgroundColor.cs | 37 - .../Filters/BlackWhite.cs | 50 -- .../Filters/Blend.cs | 60 -- .../Filters/BoxBlur.cs | 52 -- .../Filters/Brightness.cs | 52 -- .../Filters/ColorBlindness.cs | 88 -- .../Filters/Contrast.cs | 52 -- .../Filters/DetectEdges.cs | 63 -- .../Filters/Greyscale.cs | 55 -- .../Filters/GuassianBlur.cs | 52 -- .../Filters/GuassianSharpen.cs | 52 -- src/ImageProcessorCore - Copy/Filters/Hue.cs | 52 -- .../Filters/Invert.cs | 50 -- .../Filters/Kodachrome.cs | 50 -- .../Filters/Lomograph.cs | 50 -- .../Filters/Options/ColorBlindness.cs | 53 -- .../Filters/Pixelate.cs | 52 -- .../Filters/Polaroid.cs | 50 -- .../Filters/Processors/AlphaProcessor.cs | 69 -- .../Processors/BackgroundColorProcessor.cs | 78 -- .../Binarization/ThresholdProcessor.cs | 86 -- .../Filters/Processors/BlendProcessor.cs | 86 -- .../Filters/Processors/BrightnessProcessor.cs | 69 -- .../ColorMatrix/BlackWhiteProcessor.cs | 32 - .../ColorBlindness/AchromatomalyProcessor.cs | 32 - .../ColorBlindness/AchromatopsiaProcessor.cs | 32 - .../ColorBlindness/DeuteranomalyProcessor.cs | 29 - .../ColorBlindness/DeuteranopiaProcessor.cs | 29 - .../ColorBlindness/ProtanomalyProcessor.cs | 29 - .../ColorBlindness/ProtanopiaProcessor.cs | 29 - .../ColorMatrix/ColorBlindness/README.md | 4 - .../ColorBlindness/TritanomalyProcessor.cs | 29 - .../ColorBlindness/TritanopiaProcessor.cs | 29 - .../ColorMatrix/ColorMatrixFilter.cs | 68 -- .../ColorMatrix/GreyscaleBt601Processor.cs | 30 - .../ColorMatrix/GreyscaleBt709Processor.cs | 30 - .../Processors/ColorMatrix/GreyscaleMode.cs | 23 - .../Processors/ColorMatrix/HueProcessor.cs | 81 -- .../ColorMatrix/IColorMatrixFilter.cs | 27 - .../ColorMatrix/KodachromeProcessor.cs | 26 - .../ColorMatrix/LomographProcessor.cs | 32 - .../ColorMatrix/PolaroidProcessor.cs | 45 - .../ColorMatrix/SaturationProcessor.cs | 75 -- .../Processors/ColorMatrix/SepiaProcessor.cs | 33 - .../Filters/Processors/ContrastProcessor.cs | 70 -- .../Convolution/BoxBlurProcessor.cs | 103 --- .../Convolution/Convolution2DFilter.cs | 113 --- .../Convolution/Convolution2PassFilter.cs | 113 --- .../Convolution/ConvolutionFilter.cs | 88 -- .../EdgeDetection/EdgeDetector2DFilter.cs | 26 - .../EdgeDetection/EdgeDetectorFilter.cs | 26 - .../EdgeDetection/IEdgeDetectorFilter.cs | 19 - .../EdgeDetection/KayyaliProcessor.cs | 30 - .../EdgeDetection/KirschProcessor.cs | 30 - .../EdgeDetection/Laplacian3X3Processor.cs | 22 - .../EdgeDetection/Laplacian5X5Processor.cs | 24 - .../LaplacianOfGaussianProcessor.cs | 24 - .../EdgeDetection/PrewittProcessor.cs | 30 - .../EdgeDetection/RobertsCrossProcessor.cs | 28 - .../EdgeDetection/ScharrProcessor.cs | 30 - .../EdgeDetection/SobelProcessor.cs | 30 - .../Convolution/GuassianBlurProcessor.cs | 140 ---- .../Convolution/GuassianSharpenProcessor.cs | 178 ---- .../Filters/Processors/GlowProcessor.cs | 64 -- .../Filters/Processors/InvertProcessor.cs | 48 -- .../Filters/Processors/PixelateProcessor.cs | 94 --- .../Filters/Processors/VignetteProcessor.cs | 63 -- .../Filters/Saturation.cs | 52 -- .../Filters/Sepia.cs | 50 -- .../Formats/Bmp/BmpBitsPerPixel.cs | 23 - .../Formats/Bmp/BmpCompression.cs | 63 -- .../Formats/Bmp/BmpDecoder.cs | 82 -- .../Formats/Bmp/BmpDecoderCore.cs | 445 ---------- .../Formats/Bmp/BmpEncoder.cs | 53 -- .../Formats/Bmp/BmpEncoderCore.cs | 205 ----- .../Formats/Bmp/BmpFileHeader.cs | 49 -- .../Formats/Bmp/BmpFormat.cs | 19 - .../Formats/Bmp/BmpInfoHeader.cs | 82 -- .../Formats/Bmp/README.md | 8 - .../Formats/Gif/BitEncoder.cs | 132 --- .../Formats/Gif/DisposalMethod.cs | 37 - .../Formats/Gif/GifConstants.cs | 83 -- .../Formats/Gif/GifDecoder.cs | 67 -- .../Formats/Gif/GifDecoderCore.cs | 428 ---------- .../Formats/Gif/GifEncoder.cs | 62 -- .../Formats/Gif/GifEncoderCore.cs | 289 ------- .../Formats/Gif/GifFormat.cs | 19 - .../Formats/Gif/LzwDecoder.cs | 231 ----- .../Formats/Gif/LzwEncoder.cs | 385 --------- .../Formats/Gif/PackedField.cs | 194 ----- .../Formats/Gif/README.md | 4 - .../Sections/GifGraphicsControlExtension.cs | 42 - .../Gif/Sections/GifImageDescriptor.cs | 59 -- .../Sections/GifLogicalScreenDescriptor.cs | 55 -- .../Formats/IImageDecoder.cs | 49 -- .../Formats/IImageEncoder.cs | 53 -- .../Formats/IImageFormat.cs | 23 - .../Formats/Jpg/Block.cs | 44 - .../Formats/Jpg/FDCT.cs | 161 ---- .../Formats/Jpg/IDCT.cs | 163 ---- .../Formats/Jpg/JpegDecoder.cs | 149 ---- .../Jpg/JpegDecoderCore.cs.REMOVED.git-id | 1 - .../Formats/Jpg/JpegEncoder.cs | 97 --- .../Formats/Jpg/JpegEncoderCore.cs | 783 ----------------- .../Formats/Jpg/JpegFormat.cs | 19 - .../Formats/Jpg/JpegSubsample.cs | 25 - .../Formats/Jpg/README.md | 3 - .../Formats/Png/GrayscaleReader.cs | 80 -- .../Formats/Png/IColorReader.cs | 25 - .../Formats/Png/PaletteIndexReader.cs | 99 --- .../Formats/Png/PngChunk.cs | 39 - .../Formats/Png/PngChunkTypes.cs | 62 -- .../Formats/Png/PngColorTypeInformation.cs | 61 -- .../Formats/Png/PngDecoder.cs | 87 -- .../Formats/Png/PngDecoderCore.cs | 527 ------------ .../Formats/Png/PngEncoder.cs | 85 -- .../Formats/Png/PngEncoderCore.cs | 470 ----------- .../Formats/Png/PngFormat.cs | 19 - .../Formats/Png/PngHeader.cs | 62 -- .../Formats/Png/README.md | 6 - .../Formats/Png/TrueColorReader.cs | 78 -- .../Formats/Png/Zlib/Adler32.cs | 174 ---- .../Formats/Png/Zlib/Crc32.cs | 180 ---- .../Formats/Png/Zlib/IChecksum.cs | 60 -- .../Formats/Png/Zlib/README.md | 2 - .../Formats/Png/Zlib/ZlibDeflateStream.cs | 210 ----- .../Formats/Png/Zlib/ZlibInflateStream.cs | 205 ----- src/ImageProcessorCore - Copy/IImageBase.cs | 29 - src/ImageProcessorCore - Copy/IImageFrame.cs | 7 - .../IImageProcessor.cs | 72 -- .../IO/BigEndianBitConverter.cs | 48 -- .../IO/EndianBinaryReader.cs | 616 -------------- .../IO/EndianBinaryWriter.cs | 385 --------- .../IO/EndianBitConverter.cs | 724 ---------------- .../IO/Endianness.cs | 23 - .../IO/LittleEndianBitConverter.cs | 47 -- src/ImageProcessorCore - Copy/Image.cs | 291 ------- src/ImageProcessorCore - Copy/ImageBase.cs | 201 ----- .../ImageExtensions.cs | 167 ---- src/ImageProcessorCore - Copy/ImageFrame.cs | 34 - .../ImageProcessor.cs | 163 ---- .../ImageProcessorCore.xproj | 22 - .../ImageProperty.cs | 153 ---- .../Numerics/Ellipse.cs | 174 ---- .../Numerics/Point.cs | 281 ------- .../Numerics/Rectangle.cs | 291 ------- .../Numerics/Size.cs | 208 ----- .../PackedVector/Bgra32.cs | 168 ---- .../PackedVector/IPackedVector.cs | 61 -- .../PixelAccessor/Bgra32PixelAccessor.cs | 155 ---- .../PixelAccessor/IPixelAccessor.cs | 43 - .../ProgressEventArgs.cs | 23 - .../Properties/AssemblyInfo.cs | 34 - .../Quantizers/IQuantizer.cs | 28 - .../Quantizers/Octree/OctreeQuantizer.cs | 534 ------------ .../Quantizers/Octree/Quantizer.cs | 146 ---- .../Quantizers/Palette/PaletteQuantizer.cs | 134 --- .../Quantizers/QuantizedImage.cs | 98 --- .../Quantizers/Wu/Box.cs | 58 -- .../Quantizers/Wu/WuQuantizer.cs | 786 ------------------ .../Samplers/Crop.cs | 68 -- .../Samplers/EntropyCrop.cs | 37 - .../Samplers/Options/AnchorPosition.cs | 58 -- .../Samplers/Options/FlipType.cs | 28 - .../Samplers/Options/ResizeHelper.cs | 430 ---------- .../Samplers/Options/ResizeMode.cs | 49 -- .../Samplers/Options/ResizeOptions.cs | 47 -- .../Samplers/Options/RotateType.cs | 33 - src/ImageProcessorCore - Copy/Samplers/Pad.cs | 35 - .../Samplers/Processors/CropProcessor.cs | 41 - .../Processors/EntropyCropProcessor.cs | 104 --- .../Samplers/Processors/IImageSampler.cs | 19 - .../Samplers/Processors/ImageSampler.cs | 17 - .../Samplers/Processors/Matrix3x2Processor.cs | 47 -- .../Samplers/Processors/ResizeProcessor.cs | 362 -------- .../Processors/RotateFlipProcessor.cs | 231 ----- .../Samplers/Processors/RotateProcessor.cs | 68 -- .../Samplers/Processors/SkewProcessor.cs | 73 -- .../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/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 - .../Resamplers/RobidouxSoftResampler.cs | 26 - .../Samplers/Resamplers/SplineResampler.cs | 26 - .../Samplers/Resamplers/TriangleResampler.cs | 34 - .../Samplers/Resamplers/WelchResampler.cs | 33 - .../Samplers/Resize.cs | 134 --- .../Samplers/Rotate.cs | 50 -- .../Samplers/RotateFlip.cs | 38 - .../Samplers/Skew.cs | 52 -- src/ImageProcessorCore - Copy/project.json | 38 - 222 files changed, 23781 deletions(-) delete mode 100644 src/ImageProcessorCore - Copy/Bootstrapper.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Color.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/ColorConstants.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/ColorDefinitions.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/ColorTransforms.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/ColorspaceTransforms.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/Bgra32.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/CieLab.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/CieXyz.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/Cmyk.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/Hsl.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/Hsv.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/Colorspaces/YCbCr.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/IAlmostEquatable.cs delete mode 100644 src/ImageProcessorCore - Copy/Colors/RgbaComponent.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Exceptions/ImageFormatException.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Exceptions/ImageProcessingException.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Extensions/ByteExtensions.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Extensions/ComparableExtensions.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Extensions/EnumerableExtensions.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Helpers/Guard.cs delete mode 100644 src/ImageProcessorCore - Copy/Common/Helpers/ImageMaths.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Alpha.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/BackgroundColor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/BlackWhite.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Blend.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/BoxBlur.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Brightness.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/ColorBlindness.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Contrast.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/DetectEdges.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Greyscale.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/GuassianBlur.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/GuassianSharpen.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Hue.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Invert.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Kodachrome.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Lomograph.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Options/ColorBlindness.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Pixelate.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Polaroid.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/AlphaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/BackgroundColorProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Binarization/ThresholdProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/BlendProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/BrightnessProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/README.md delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt601Processor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt709Processor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleMode.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/HueProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/KodachromeProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/LomographProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/PolaroidProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SaturationProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SepiaProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/ContrastProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/BoxBlurProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2DFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2PassFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/ConvolutionFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianBlurProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianSharpenProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/GlowProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/InvertProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/PixelateProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Processors/VignetteProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Saturation.cs delete mode 100644 src/ImageProcessorCore - Copy/Filters/Sepia.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpBitsPerPixel.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpCompression.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpFileHeader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpFormat.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/BmpInfoHeader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Bmp/README.md delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/BitEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/DisposalMethod.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifConstants.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifDecoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifEncoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/GifFormat.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/LzwDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/LzwEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/PackedField.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/README.md delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifGraphicsControlExtension.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifImageDescriptor.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/IImageDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/IImageEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/IImageFormat.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/Block.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/FDCT.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/IDCT.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegFormat.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/JpegSubsample.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Jpg/README.md delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/GrayscaleReader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/IColorReader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PaletteIndexReader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngChunk.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngChunkTypes.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngColorTypeInformation.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngDecoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngDecoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngEncoder.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngEncoderCore.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngFormat.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/PngHeader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/README.md delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/TrueColorReader.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/Adler32.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/Crc32.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/IChecksum.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/README.md delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibDeflateStream.cs delete mode 100644 src/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibInflateStream.cs delete mode 100644 src/ImageProcessorCore - Copy/IImageBase.cs delete mode 100644 src/ImageProcessorCore - Copy/IImageFrame.cs delete mode 100644 src/ImageProcessorCore - Copy/IImageProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/BigEndianBitConverter.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/EndianBinaryReader.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/EndianBinaryWriter.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/EndianBitConverter.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/Endianness.cs delete mode 100644 src/ImageProcessorCore - Copy/IO/LittleEndianBitConverter.cs delete mode 100644 src/ImageProcessorCore - Copy/Image.cs delete mode 100644 src/ImageProcessorCore - Copy/ImageBase.cs delete mode 100644 src/ImageProcessorCore - Copy/ImageExtensions.cs delete mode 100644 src/ImageProcessorCore - Copy/ImageFrame.cs delete mode 100644 src/ImageProcessorCore - Copy/ImageProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/ImageProcessorCore.xproj delete mode 100644 src/ImageProcessorCore - Copy/ImageProperty.cs delete mode 100644 src/ImageProcessorCore - Copy/Numerics/Ellipse.cs delete mode 100644 src/ImageProcessorCore - Copy/Numerics/Point.cs delete mode 100644 src/ImageProcessorCore - Copy/Numerics/Rectangle.cs delete mode 100644 src/ImageProcessorCore - Copy/Numerics/Size.cs delete mode 100644 src/ImageProcessorCore - Copy/PackedVector/Bgra32.cs delete mode 100644 src/ImageProcessorCore - Copy/PackedVector/IPackedVector.cs delete mode 100644 src/ImageProcessorCore - Copy/PixelAccessor/Bgra32PixelAccessor.cs delete mode 100644 src/ImageProcessorCore - Copy/PixelAccessor/IPixelAccessor.cs delete mode 100644 src/ImageProcessorCore - Copy/ProgressEventArgs.cs delete mode 100644 src/ImageProcessorCore - Copy/Properties/AssemblyInfo.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/IQuantizer.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/Octree/OctreeQuantizer.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/Octree/Quantizer.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/Palette/PaletteQuantizer.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/QuantizedImage.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/Wu/Box.cs delete mode 100644 src/ImageProcessorCore - Copy/Quantizers/Wu/WuQuantizer.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Crop.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/EntropyCrop.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/AnchorPosition.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/FlipType.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/ResizeHelper.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/ResizeMode.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/ResizeOptions.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Options/RotateType.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Pad.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/CropProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/EntropyCropProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/IImageSampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/ImageSampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/Matrix3x2Processor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/ResizeProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/RotateFlipProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/RotateProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Processors/SkewProcessor.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/BicubicResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/BoxResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/CatmullRomResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/HermiteResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/IResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos3Resampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos5Resampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos8Resampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/MitchellNetravaliResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/NearestNeighborResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSharpResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSoftResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/SplineResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/TriangleResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resamplers/WelchResampler.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Resize.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Rotate.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/RotateFlip.cs delete mode 100644 src/ImageProcessorCore - Copy/Samplers/Skew.cs delete mode 100644 src/ImageProcessorCore - Copy/project.json diff --git a/src/ImageProcessorCore - Copy/Bootstrapper.cs b/src/ImageProcessorCore - Copy/Bootstrapper.cs deleted file mode 100644 index 5f2978534..000000000 --- a/src/ImageProcessorCore - Copy/Bootstrapper.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Text; - - using ImageProcessorCore.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; - - private readonly Dictionary pixelAccessors; - - /// - /// Prevents a default instance of the class from being created. - /// - private Bootstrapper() - { - this.imageFormats = new List - { - new BmpFormat(), - new JpegFormat(), - new PngFormat(), - new GifFormat() - }; - - this.pixelAccessors = new Dictionary - { - { typeof(Bgra32), typeof(Bgra32PixelAccessor) } - }; - } - - /// - /// Gets the current bootstrapper instance. - /// - public static Bootstrapper Instance = Lazy.Value; - - /// - /// Gets the list of supported - /// - public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormats); - - /// - /// Adds a new to the collection of supported image formats. - /// - /// The new format to add. - public void AddImageFormat(IImageFormat format) - { - this.imageFormats.Add(format); - } - - /// - /// Gets an instance of the correct for the packed vector. - /// - /// The type of pixel data. - /// The image - /// The - public IPixelAccessor GetPixelAccessor(Image image) - where TPackedVector : IPackedVector - { - Type packed = typeof(TPackedVector); - if (!this.pixelAccessors.ContainsKey(packed)) - { - // TODO: Double check this. It should work... - return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image); - } - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine("PixelAccessor cannot be loaded. Available accessors:"); - - foreach (Type value in this.pixelAccessors.Values) - { - stringBuilder.AppendLine("-" + value.Name); - } - - throw new NotSupportedException(stringBuilder.ToString()); - } - - /// - /// Gets an instance of the correct for the packed vector. - /// - /// The type of pixel data. - /// The image - /// The - public IPixelAccessor GetPixelAccessor(ImageFrame image) - where TPackedVector : IPackedVector - { - Type packed = typeof(TPackedVector); - if (!this.pixelAccessors.ContainsKey(packed)) - { - return (IPixelAccessor)Activator.CreateInstance(this.pixelAccessors[packed], image); - } - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine("PixelAccessor cannot be loaded. Available accessors:"); - - foreach (Type value in this.pixelAccessors.Values) - { - stringBuilder.AppendLine("-" + value.Name); - } - - throw new NotSupportedException(stringBuilder.ToString()); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/Color.cs b/src/ImageProcessorCore - Copy/Colors/Color.cs deleted file mode 100644 index 0e47e03e1..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Color.cs +++ /dev/null @@ -1,518 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.ComponentModel; - using System.Numerics; - using System.Runtime.CompilerServices; - - /// - /// Represents a four-component color using red, green, blue, and alpha data. - /// Each component is stored in premultiplied format multiplied by the alpha component. - /// - /// - /// 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 : IEquatable, IAlmostEquatable - { - /// - /// Represents an empty that has R, G, B, and A values set to zero. - /// - public static readonly Color Empty = default(Color); - - /// - /// 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 red component of this . - /// The green component of this . - /// The blue component of this . - /// The alpha component of this . - public Color(float r, float g, float b, float a = 1) - : this() - { - this.backingVector = new Vector4(r, g, b, a); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The hexadecimal representation of the combined color components arranged - /// in rgb, rrggbb, or aarrggbb format to match web syntax. - /// - public Color(string hex) - : this() - { - // Hexadecimal representations are layed out AARRGGBB to we need to do some reordering. - hex = hex.StartsWith("#") ? hex.Substring(1) : hex; - - if (hex.Length != 8 && hex.Length != 6 && hex.Length != 3) - { - throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); - } - - if (hex.Length == 8) - { - float r = Convert.ToByte(hex.Substring(2, 2), 16); - float g = Convert.ToByte(hex.Substring(4, 2), 16); - float b = Convert.ToByte(hex.Substring(6, 2), 16); - float a = Convert.ToByte(hex.Substring(0, 2), 16); - - // Do division of Vector4 instead of each component to utilize SIMD optimizations - this.backingVector = new Vector4(r, g, b, a) / 255f; - this.backingVector = FromNonPremultiplied(this.backingVector, this.A); - - } - else if (hex.Length == 6) - { - float r = Convert.ToByte(hex.Substring(0, 2), 16); - float g = Convert.ToByte(hex.Substring(2, 2), 16); - float b = Convert.ToByte(hex.Substring(4, 2), 16); - float a = 255f; - - // Do division of Vector4 instead of each component to utilize SIMD optimizations - this.backingVector = new Vector4(r, g, b, a) / 255f; - } - else - { - string rh = char.ToString(hex[0]); - string gh = char.ToString(hex[1]); - string bh = char.ToString(hex[2]); - - float r = Convert.ToByte(rh + rh, 16); - float g = Convert.ToByte(gh + gh, 16); - float b = Convert.ToByte(bh + bh, 16); - float a = 255f; - - this.backingVector = new Vector4(r, g, b, a) / 255f; - } - } - - /// - /// Initializes a new instance of the struct. - /// - /// The vector. - public Color(Vector4 vector) - { - this.backingVector = vector; - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector representing the red, green, and blue componenets. - /// - public Color(Vector3 vector) - { - this.backingVector = new Vector4(vector, 1); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector representing the red, green, and blue componenets. - /// - /// The alpha component. - public Color(Vector3 vector, float alpha) - { - this.backingVector = new Vector4(vector, alpha); - } - - /// - /// Gets or sets the red component of the color. - /// - public float R - { - get - { - return this.backingVector.X; - } - - set - { - this.backingVector.X = value; - } - } - - /// - /// Gets or sets the green component of the color. - /// - public float G - { - get - { - return this.backingVector.Y; - } - - set - { - this.backingVector.Y = value; - } - } - - /// - /// Gets or sets the blue component of the color. - /// - public float B - { - get - { - return this.backingVector.Z; - } - - set - { - this.backingVector.Z = value; - } - } - - /// - /// Gets or sets the alpha component of the color. - /// - public float A - { - get - { - return 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 this color with the component values clamped from 0 to 1. - /// - public Color Limited => new Color(Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One)); - - /// - /// Computes the product of multiplying a color by a given factor. - /// - /// The color. - /// The multiplication factor. - /// - /// The - /// - public static Color operator *(Color color, float factor) - { - return new Color(color.backingVector * factor); - } - - /// - /// Computes the product of multiplying a color by a given factor. - /// - /// The multiplication factor. - /// The color. - /// - /// The - /// - public static Color operator *(float factor, Color color) - { - return new Color(color.backingVector * factor); - } - - /// - /// Computes the product of multiplying two colors. - /// - /// The color on the left hand of the operand. - /// The color on the right hand of the operand. - /// - /// The - /// - public static Color operator *(Color left, Color right) - { - return new Color(left.backingVector * right.backingVector); - } - - /// - /// Computes the sum of adding two colors. - /// - /// The color on the left hand of the operand. - /// The color on the right hand of the operand. - /// - /// The - /// - public static Color operator +(Color left, Color right) - { - return new Color(left.backingVector + right.backingVector); - } - - /// - /// Computes the difference left by subtracting one color from another. - /// - /// The color on the left hand of the operand. - /// The color on the right hand of the operand. - /// - /// The - /// - public static Color operator -(Color left, Color right) - { - return new Color(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 ==(Color left, Color 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 !=(Color left, Color right) - { - return !left.Equals(right); - } - - /// - /// Returns a new color whose components are the average of the components of first and second. - /// - /// The first color. - /// The second color. - /// - /// The - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Color Average(Color first, Color second) - { - return new Color((first.backingVector + second.backingVector) * .5f); - } - - /// - /// Compresses a linear color signal to its sRGB equivalent. - /// - /// - /// - /// The whose signal to compress. - /// The . - public static Color Compress(Color linear) - { - // TODO: Is there a faster way to do this? - float r = Compress(linear.R); - float g = Compress(linear.G); - float b = Compress(linear.B); - - return new Color(r, g, b, linear.A); - } - - /// - /// Expands an sRGB color signal to its linear equivalent. - /// - /// - /// - /// The whose signal to expand. - /// The . - public static Color Expand(Color gamma) - { - // TODO: Is there a faster way to do this? - float r = Expand(gamma.R); - float g = Expand(gamma.G); - float b = Expand(gamma.B); - - return new Color(r, g, b, gamma.A); - } - - /// - /// Converts a non-premultipled alpha to a - /// that contains premultiplied alpha. - /// - /// The to convert. - /// The . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Color FromNonPremultiplied(Color color) - { - return new Color(FromNonPremultiplied(color.backingVector, color.A)); - } - - /// - /// Converts a non-premultiplied alpha Vector4 to a Vector4 that contains premultiplied alpha. - /// - /// The vector to convert. - /// The alpha to use in conversion. - /// The Vector4 with premultiplied alpha. - private static Vector4 FromNonPremultiplied(Vector4 vector, float alpha) - { - return vector * new Vector4(alpha, alpha, alpha, 1); - } - - /// - /// Converts a premultipled alpha to a - /// that contains non-premultiplied alpha. - /// - /// The to convert. - /// The . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Color ToNonPremultiplied(Color color) - { - float a = color.A; - if (Math.Abs(a) < Epsilon) - { - return new Color(color.backingVector); - } - - return new Color(color.backingVector / new Vector4(a, a, a, 1)); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ToVector4() - { - return new Vector4(this.R, this.G, this.B, this.A); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - public Vector3 ToVector3() - { - return new Vector3(this.R, this.G, this.B); - } - - /// - public override int GetHashCode() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Color [ Empty ]"; - } - - return $"Color [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##}, A={this.A:#0.##} ]"; - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) - { - if (obj is Color) - { - return this.Equals((Color)obj); - } - - return false; - } - - /// - public bool Equals(Color other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AlmostEquals(Color other, float precision) - { - Vector4 result = Vector4.Abs(this.backingVector - other.backingVector); - - return result.X < precision - && result.Y < precision - && result.Z < precision - && result.W < precision; - } - - /// - /// 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); - } - - /// - /// 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(Color color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/ColorConstants.cs b/src/ImageProcessorCore - Copy/Colors/ColorConstants.cs deleted file mode 100644 index ed9718423..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Colors/ColorDefinitions.cs b/src/ImageProcessorCore - Copy/Colors/ColorDefinitions.cs deleted file mode 100644 index aaf99bb1b..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// Represents a four-component color using red, green, blue, and alpha data. - /// Each component is stored in premultiplied format multiplied by the alpha component. - /// - /// - /// 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 a hex triplet value of #F0F8FF. - /// - public static readonly Color AliceBlue = new Color(240 / 255f, 248 / 255f, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FAEBD7. - /// - public static readonly Color AntiqueWhite = new Color(250 / 255f, 235 / 255f, 215 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00FFFF. - /// - public static readonly Color Aqua = new Color(0, 1, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #7FFFD4. - /// - public static readonly Color Aquamarine = new Color(127 / 255f, 1, 212 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F0FFFF. - /// - public static readonly Color Azure = new Color(240 / 255f, 1, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F5F5DC. - /// - public static readonly Color Beige = new Color(245 / 255f, 245 / 255f, 220 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFE4C4. - /// - public static readonly Color Bisque = new Color(1, 228 / 255f, 196 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #000000. - /// - public static readonly Color Black = new Color(0, 0, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFEBCD. - /// - public static readonly Color BlanchedAlmond = new Color(1, 235 / 255f, 205 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #0000FF. - /// - public static readonly Color Blue = new Color(0, 0, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #8A2BE2. - /// - public static readonly Color BlueViolet = new Color(138 / 255f, 43 / 255f, 226 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #A52A2A. - /// - public static readonly Color Brown = new Color(165 / 255f, 42 / 255f, 42 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DEB887. - /// - public static readonly Color BurlyWood = new Color(222 / 255f, 184 / 255f, 135 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #5F9EA0. - /// - public static readonly Color CadetBlue = new Color(95 / 255f, 158 / 255f, 160 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #7FFF00. - /// - public static readonly Color Chartreuse = new Color(127 / 255f, 1, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #D2691E. - /// - public static readonly Color Chocolate = new Color(210 / 255f, 105 / 255f, 30 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF7F50. - /// - public static readonly Color Coral = new Color(1, 127 / 255f, 80 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #6495ED. - /// - public static readonly Color CornflowerBlue = new Color(100 / 255f, 149 / 255f, 237 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFF8DC. - /// - public static readonly Color Cornsilk = new Color(1, 248 / 255f, 220 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DC143C. - /// - public static readonly Color Crimson = new Color(220 / 255f, 20 / 255f, 60 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00FFFF. - /// - public static readonly Color Cyan = new Color(0, 1, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00008B. - /// - public static readonly Color DarkBlue = new Color(0, 0, 139 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #008B8B. - /// - public static readonly Color DarkCyan = new Color(0, 139 / 255f, 139 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #B8860B. - /// - public static readonly Color DarkGoldenrod = new Color(184 / 255f, 134 / 255f, 11 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #A9A9A9. - /// - public static readonly Color DarkGray = new Color(169 / 255f, 169 / 255f, 169 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #006400. - /// - public static readonly Color DarkGreen = new Color(0, 100 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #BDB76B. - /// - public static readonly Color DarkKhaki = new Color(189 / 255f, 183 / 255f, 107 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #8B008B. - /// - public static readonly Color DarkMagenta = new Color(139 / 255f, 0, 139 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #556B2F. - /// - public static readonly Color DarkOliveGreen = new Color(85 / 255f, 107 / 255f, 47 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF8C00. - /// - public static readonly Color DarkOrange = new Color(1, 140 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #9932CC. - /// - public static readonly Color DarkOrchid = new Color(153 / 255f, 50 / 255f, 204 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #8B0000. - /// - public static readonly Color DarkRed = new Color(139 / 255f, 0, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #E9967A. - /// - public static readonly Color DarkSalmon = new Color(233 / 255f, 150 / 255f, 122 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #8FBC8B. - /// - public static readonly Color DarkSeaGreen = new Color(143 / 255f, 188 / 255f, 139 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #483D8B. - /// - public static readonly Color DarkSlateBlue = new Color(72 / 255f, 61 / 255f, 139 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #2F4F4F. - /// - public static readonly Color DarkSlateGray = new Color(47 / 255f, 79 / 255f, 79 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00CED1. - /// - public static readonly Color DarkTurquoise = new Color(0, 206 / 255f, 209 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #9400D3. - /// - public static readonly Color DarkViolet = new Color(148 / 255f, 0, 211 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF1493. - /// - public static readonly Color DeepPink = new Color(1, 20 / 255f, 147 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00BFFF. - /// - public static readonly Color DeepSkyBlue = new Color(0, 191 / 255f, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #696969. - /// - public static readonly Color DimGray = new Color(105 / 255f, 105 / 255f, 105 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #1E90FF. - /// - public static readonly Color DodgerBlue = new Color(30 / 255f, 144 / 255f, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #B22222. - /// - public static readonly Color Firebrick = new Color(178 / 255f, 34 / 255f, 34 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFAF0. - /// - public static readonly Color FloralWhite = new Color(1, 250 / 255f, 240 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #228B22. - /// - public static readonly Color ForestGreen = new Color(34 / 255f, 139 / 255f, 34 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF00FF. - /// - public static readonly Color Fuchsia = new Color(1, 0, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DCDCDC. - /// - public static readonly Color Gainsboro = new Color(220 / 255f, 220 / 255f, 220 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F8F8FF. - /// - public static readonly Color GhostWhite = new Color(248 / 255f, 248 / 255f, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFD700. - /// - public static readonly Color Gold = new Color(1, 215 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DAA520. - /// - public static readonly Color Goldenrod = new Color(218 / 255f, 165 / 255f, 32 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #808080. - /// - public static readonly Color Gray = new Color(128 / 255f, 128 / 255f, 128 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #008000. - /// - public static readonly Color Green = new Color(0, 128 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #ADFF2F. - /// - public static readonly Color GreenYellow = new Color(173 / 255f, 1, 47 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F0FFF0. - /// - public static readonly Color Honeydew = new Color(240 / 255f, 1, 240 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF69B4. - /// - public static readonly Color HotPink = new Color(1, 105 / 255f, 180 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #CD5C5C. - /// - public static readonly Color IndianRed = new Color(205 / 255f, 92 / 255f, 92 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #4B0082. - /// - public static readonly Color Indigo = new Color(75 / 255f, 0, 130 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFFF0. - /// - public static readonly Color Ivory = new Color(1, 1, 240 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F0E68C. - /// - public static readonly Color Khaki = new Color(240 / 255f, 230 / 255f, 140 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #E6E6FA. - /// - public static readonly Color Lavender = new Color(230 / 255f, 230 / 255f, 250 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFF0F5. - /// - public static readonly Color LavenderBlush = new Color(1, 240 / 255f, 245 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #7CFC00. - /// - public static readonly Color LawnGreen = new Color(124 / 255f, 252 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFACD. - /// - public static readonly Color LemonChiffon = new Color(1, 250 / 255f, 205 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #ADD8E6. - /// - public static readonly Color LightBlue = new Color(173 / 255f, 216 / 255f, 230 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F08080. - /// - public static readonly Color LightCoral = new Color(240 / 255f, 128 / 255f, 128 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #E0FFFF. - /// - public static readonly Color LightCyan = new Color(224 / 255f, 1, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FAFAD2. - /// - public static readonly Color LightGoldenrodYellow = new Color(250 / 255f, 250 / 255f, 210 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #90EE90. - /// - public static readonly Color LightGreen = new Color(144 / 255f, 238 / 255f, 144 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #D3D3D3. - /// - public static readonly Color LightGray = new Color(211 / 255f, 211 / 255f, 211 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFB6C1. - /// - public static readonly Color LightPink = new Color(1, 182 / 255f, 193 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFA07A. - /// - public static readonly Color LightSalmon = new Color(1, 160 / 255f, 122 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #20B2AA. - /// - public static readonly Color LightSeaGreen = new Color(32 / 255f, 178 / 255f, 170 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #87CEFA. - /// - public static readonly Color LightSkyBlue = new Color(135 / 255f, 206 / 255f, 250 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #778899. - /// - public static readonly Color LightSlateGray = new Color(119 / 255f, 136 / 255f, 153 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #B0C4DE. - /// - public static readonly Color LightSteelBlue = new Color(176 / 255f, 196 / 255f, 222 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFFE0. - /// - public static readonly Color LightYellow = new Color(1, 1, 224 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00FF00. - /// - public static readonly Color Lime = new Color(0, 1, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #32CD32. - /// - public static readonly Color LimeGreen = new Color(50 / 255f, 205 / 255f, 50 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FAF0E6. - /// - public static readonly Color Linen = new Color(250 / 255f, 240 / 255f, 230 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF00FF. - /// - public static readonly Color Magenta = new Color(1, 0, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #800000. - /// - public static readonly Color Maroon = new Color(128 / 255f, 0, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #66CDAA. - /// - public static readonly Color MediumAquamarine = new Color(102 / 255f, 205 / 255f, 170 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #0000CD. - /// - public static readonly Color MediumBlue = new Color(0, 0, 205 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #BA55D3. - /// - public static readonly Color MediumOrchid = new Color(186 / 255f, 85 / 255f, 211 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #9370DB. - /// - public static readonly Color MediumPurple = new Color(147 / 255f, 112 / 255f, 219 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #3CB371. - /// - public static readonly Color MediumSeaGreen = new Color(60 / 255f, 179 / 255f, 113 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #7B68EE. - /// - public static readonly Color MediumSlateBlue = new Color(123 / 255f, 104 / 255f, 238 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00FA9A. - /// - public static readonly Color MediumSpringGreen = new Color(0, 250 / 255f, 154 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #48D1CC. - /// - public static readonly Color MediumTurquoise = new Color(72 / 255f, 209 / 255f, 204 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #C71585. - /// - public static readonly Color MediumVioletRed = new Color(199 / 255f, 21 / 255f, 133 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #191970. - /// - public static readonly Color MidnightBlue = new Color(25 / 255f, 25 / 255f, 112 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F5FFFA. - /// - public static readonly Color MintCream = new Color(245 / 255f, 1, 250 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFE4E1. - /// - public static readonly Color MistyRose = new Color(1, 228 / 255f, 225 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFE4B5. - /// - public static readonly Color Moccasin = new Color(1, 228 / 255f, 181 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFDEAD. - /// - public static readonly Color NavajoWhite = new Color(1, 222 / 255f, 173 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #000080. - /// - public static readonly Color Navy = new Color(0, 0, 128 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FDF5E6. - /// - public static readonly Color OldLace = new Color(253 / 255f, 245 / 255f, 230 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #808000. - /// - public static readonly Color Olive = new Color(128 / 255f, 128 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #6B8E23. - /// - public static readonly Color OliveDrab = new Color(107 / 255f, 142 / 255f, 35 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFA500. - /// - public static readonly Color Orange = new Color(1, 165 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF4500. - /// - public static readonly Color OrangeRed = new Color(1, 69 / 255f, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DA70D6. - /// - public static readonly Color Orchid = new Color(218 / 255f, 112 / 255f, 214 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #EEE8AA. - /// - public static readonly Color PaleGoldenrod = new Color(238 / 255f, 232 / 255f, 170 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #98FB98. - /// - public static readonly Color PaleGreen = new Color(152 / 255f, 251 / 255f, 152 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #AFEEEE. - /// - public static readonly Color PaleTurquoise = new Color(175 / 255f, 238 / 255f, 238 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DB7093. - /// - public static readonly Color PaleVioletRed = new Color(219 / 255f, 112 / 255f, 147 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFEFD5. - /// - public static readonly Color PapayaWhip = new Color(1, 239 / 255f, 213 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFDAB9. - /// - public static readonly Color PeachPuff = new Color(1, 218 / 255f, 185 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #CD853F. - /// - public static readonly Color Peru = new Color(205 / 255f, 133 / 255f, 63 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFC0CB. - /// - public static readonly Color Pink = new Color(1, 192 / 255f, 203 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #DDA0DD. - /// - public static readonly Color Plum = new Color(221 / 255f, 160 / 255f, 221 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #B0E0E6. - /// - public static readonly Color PowderBlue = new Color(176 / 255f, 224 / 255f, 230 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #800080. - /// - public static readonly Color Purple = new Color(128 / 255f, 0, 128 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #663399. - /// - public static readonly Color RebeccaPurple = new Color(102 / 255f, 51 / 255f, 153 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF0000. - /// - public static readonly Color Red = new Color(1, 0, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #BC8F8F. - /// - public static readonly Color RosyBrown = new Color(188 / 255f, 143 / 255f, 143 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #4169E1. - /// - public static readonly Color RoyalBlue = new Color(65 / 255f, 105 / 255f, 225 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #8B4513. - /// - public static readonly Color SaddleBrown = new Color(139 / 255f, 69 / 255f, 19 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FA8072. - /// - public static readonly Color Salmon = new Color(250 / 255f, 128 / 255f, 114 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F4A460. - /// - public static readonly Color SandyBrown = new Color(244 / 255f, 164 / 255f, 96 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #2E8B57. - /// - public static readonly Color SeaGreen = new Color(46 / 255f, 139 / 255f, 87 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFF5EE. - /// - public static readonly Color SeaShell = new Color(1, 245 / 255f, 238 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #A0522D. - /// - public static readonly Color Sienna = new Color(160 / 255f, 82 / 255f, 45 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #C0C0C0. - /// - public static readonly Color Silver = new Color(192 / 255f, 192 / 255f, 192 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #87CEEB. - /// - public static readonly Color SkyBlue = new Color(135 / 255f, 206 / 255f, 235 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #6A5ACD. - /// - public static readonly Color SlateBlue = new Color(106 / 255f, 90 / 255f, 205 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #708090. - /// - public static readonly Color SlateGray = new Color(112 / 255f, 128 / 255f, 144 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFAFA. - /// - public static readonly Color Snow = new Color(1, 250 / 255f, 250 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #00FF7F. - /// - public static readonly Color SpringGreen = new Color(0, 1, 127 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #4682B4. - /// - public static readonly Color SteelBlue = new Color(70 / 255f, 130 / 255f, 180 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #D2B48C. - /// - public static readonly Color Tan = new Color(210 / 255f, 180 / 255f, 140 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #008080. - /// - public static readonly Color Teal = new Color(0, 128 / 255f, 128 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #D8BFD8. - /// - public static readonly Color Thistle = new Color(216 / 255f, 191 / 255f, 216 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FF6347. - /// - public static readonly Color Tomato = new Color(1, 99 / 255f, 71 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #40E0D0. - /// - public static readonly Color Turquoise = new Color(64 / 255f, 224 / 255f, 208 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #EE82EE. - /// - public static readonly Color Violet = new Color(238 / 255f, 130 / 255f, 238 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F5DEB3. - /// - public static readonly Color Wheat = new Color(245 / 255f, 222 / 255f, 179 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFFFF. - /// - public static readonly Color White = new Color(1, 1, 1); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #F5F5F5. - /// - public static readonly Color WhiteSmoke = new Color(245 / 255f, 245 / 255f, 245 / 255f); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #FFFF00. - /// - public static readonly Color Yellow = new Color(1, 1, 0); - - /// - /// Represents a matching the W3C definition that has a hex triplet value of #9ACD32. - /// - public static readonly Color YellowGreen = new Color(154 / 255f, 205 / 255f, 50 / 255f); - - /// - /// Represents a system-defined that has an ARGB value of #00FFFFFF. - /// - public static readonly Color Transparent = new Color(1, 1, 1, 0); - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/ColorTransforms.cs b/src/ImageProcessorCore - Copy/Colors/ColorTransforms.cs deleted file mode 100644 index 2a0da9407..000000000 --- a/src/ImageProcessorCore - Copy/Colors/ColorTransforms.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - - /// - /// Represents a four-component color using red, green, blue, and alpha data. - /// Each component is stored in premultiplied format multiplied by the alpha component. - /// - /// - /// 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; - } - - return new Color(source.backingVector * destination.backingVector); - } - - /// - /// Linearly interpolates from one color to another based on the given amount. - /// - /// The first color value. - /// The second color value. - /// - /// The weight value. At amount = 0, "from" is returned, at amount = 1, "to" is returned. - /// - /// - /// The - /// - public static Color Lerp(Color source, Color destination, float amount) - { - amount = amount.Clamp(0f, 1f); - - if (Math.Abs(source.A - 1) < Epsilon && Math.Abs(destination.A - 1) < Epsilon) - { - return source + ((destination - source) * amount); - } - - // Premultiplied. - return (source * (1 - amount)) + destination; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/ColorspaceTransforms.cs b/src/ImageProcessorCore - Copy/Colors/ColorspaceTransforms.cs deleted file mode 100644 index 50d0af315..000000000 --- a/src/ImageProcessorCore - Copy/Colors/ColorspaceTransforms.cs +++ /dev/null @@ -1,285 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - - /// - /// Represents a four-component color using red, green, blue, and alpha data. - /// Each component is stored in premultiplied format multiplied by the alpha component. - /// - /// - /// 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 - { - /// - /// 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 / 255f, color.G / 255f, color.B / 255f, color.A / 255f); - } - - /// - /// 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); - } - - /// - /// 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) - { - float y = color.Y; - float cb = color.Cb - 128; - float cr = color.Cr - 128; - - float r = (float)(y + (1.402 * cr)).Clamp(0, 255) / 255f; - float g = (float)(y - (0.34414 * cb) - (0.71414 * cr)).Clamp(0, 255) / 255f; - float b = (float)(y + (1.772 * cb)).Clamp(0, 255) / 255f; - - 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); - - return Color.Compress(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(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); - } - - /// - /// 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); - } - - /// - /// 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 Color.Compress(new Color(r, g, b)); - } - - /// - /// 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/ImageProcessorCore - Copy/Colors/Colorspaces/Bgra32.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/Bgra32.cs deleted file mode 100644 index cc4fad541..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Colorspaces/Bgra32.cs +++ /dev/null @@ -1,168 +0,0 @@ -//// -//// Copyright (c) James Jackson-South and contributors. -//// Licensed under the Apache License, Version 2.0. -//// - -//namespace ImageProcessorCore -//{ -// 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) -// { -// color = color.Limited * 255f; -// return new Bgra32((byte)color.B, (byte)color.G, (byte)color.R, (byte)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/ImageProcessorCore - Copy/Colors/Colorspaces/CieLab.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/CieLab.cs deleted file mode 100644 index cce92601a..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Colorspaces/CieLab.cs +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 - color = Color.Expand(color); - - float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F); - float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F); - float z = (color.R * 0.0193F) + (color.G * 0.1192F) + (color.B * 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/ImageProcessorCore - Copy/Colors/Colorspaces/CieXyz.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/CieXyz.cs deleted file mode 100644 index 8f41c8abb..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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) - { - color = Color.Expand(color); - - float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F); - float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F); - float z = (color.R * 0.0193F) + (color.G * 0.1192F) + (color.B * 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/ImageProcessorCore - Copy/Colors/Colorspaces/Cmyk.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/Cmyk.cs deleted file mode 100644 index b343288a6..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Colorspaces/Cmyk.cs +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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) - { - color = color.Limited; - - float c = 1f - color.R; - float m = 1f - color.G; - float y = 1f - color.B; - - 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/ImageProcessorCore - Copy/Colors/Colorspaces/Hsl.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/Hsl.cs deleted file mode 100644 index e6eee42e3..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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) - { - color = Color.ToNonPremultiplied(color.Limited); - float r = color.R; - float g = color.G; - float b = color.B; - - 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/ImageProcessorCore - Copy/Colors/Colorspaces/Hsv.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/Hsv.cs deleted file mode 100644 index 914df51c9..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Colorspaces/Hsv.cs +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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) - { - color = Color.ToNonPremultiplied(color.Limited); - float r = color.R; - float g = color.G; - float b = color.B; - - 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/ImageProcessorCore - Copy/Colors/Colorspaces/YCbCr.cs b/src/ImageProcessorCore - Copy/Colors/Colorspaces/YCbCr.cs deleted file mode 100644 index 5c47c6c08..000000000 --- a/src/ImageProcessorCore - Copy/Colors/Colorspaces/YCbCr.cs +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an YCbCr (luminance, chroma, chroma) color conforming to the - /// Full range standard used in digital imaging systems. - /// - /// - public struct YCbCr : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has Y, Cb, and Cr values set to zero. - /// - public static readonly YCbCr Empty = default(YCbCr); - - /// - /// 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. - /// The cb chroma component. - /// The cr chroma component. - public YCbCr(float y, float cb, float cr) - : this() - { - this.backingVector = Vector3.Clamp(new Vector3(y, cb, cr), Vector3.Zero, new Vector3(255)); - } - - /// - /// Gets the Y luminance component. - /// A value ranging between 0 and 255. - /// - public float Y => this.backingVector.X; - - /// - /// Gets the Cb chroma component. - /// A value ranging between 0 and 255. - /// - public float Cb => this.backingVector.Y; - - /// - /// Gets the Cr chroma component. - /// A value ranging between 0 and 255. - /// - public float Cr => 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 YCbCr(Color color) - { - color = Color.ToNonPremultiplied(color.Limited) * 255f; - float r = color.R; - float g = color.G; - float b = color.B; - - float y = (float)((0.299 * r) + (0.587 * g) + (0.114 * b)); - float cb = 128 + (float)((-0.168736 * r) - (0.331264 * g) + (0.5 * b)); - float cr = 128 + (float)((0.5 * r) - (0.418688 * g) - (0.081312 * 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() - { - return GetHashCode(this); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "YCbCr [ Empty ]"; - } - - return $"YCbCr [ Y={this.Y:#0.##}, Cb={this.Cb:#0.##}, Cr={this.Cr:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is YCbCr) - { - return this.Equals((YCbCr)obj); - } - - return false; - } - - /// - public bool Equals(YCbCr other) - { - return this.AlmostEquals(other, Epsilon); - } - - /// - public bool AlmostEquals(YCbCr 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(YCbCr color) => color.backingVector.GetHashCode(); - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/IAlmostEquatable.cs b/src/ImageProcessorCore - Copy/Colors/IAlmostEquatable.cs deleted file mode 100644 index 4677c3415..000000000 --- a/src/ImageProcessorCore - Copy/Colors/IAlmostEquatable.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 TP : 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(T other, TP precision); - } -} diff --git a/src/ImageProcessorCore - Copy/Colors/RgbaComponent.cs b/src/ImageProcessorCore - Copy/Colors/RgbaComponent.cs deleted file mode 100644 index a4b668cb6..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// Enumerates the RGBA (red, green, blue, alpha) color components. - /// - public enum RgbaComponent - { - /// - /// The blue component. - /// - B = 0, - - /// - /// The green component. - /// - G = 1, - - /// - /// The red component. - /// - R = 2, - - /// - /// The alpha component. - /// - A = 3 - } -} diff --git a/src/ImageProcessorCore - Copy/Common/Exceptions/ImageFormatException.cs b/src/ImageProcessorCore - Copy/Common/Exceptions/ImageFormatException.cs deleted file mode 100644 index 87fb38159..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Common/Exceptions/ImageProcessingException.cs b/src/ImageProcessorCore - Copy/Common/Exceptions/ImageProcessingException.cs deleted file mode 100644 index 7899dcf44..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Common/Extensions/ByteExtensions.cs b/src/ImageProcessorCore - Copy/Common/Extensions/ByteExtensions.cs deleted file mode 100644 index 05b71bb2f..000000000 --- a/src/ImageProcessorCore - Copy/Common/Extensions/ByteExtensions.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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[] bytes, int bits) - { - Guard.NotNull(bytes, "bytes"); - Guard.MustBeGreaterThan(bits, 0, "bits"); - - byte[] result; - - if (bits < 8) - { - result = new byte[bytes.Length * 8 / bits]; - - // BUGFIX I dont think it should be there, but I am not sure if it breaks something else - // int factor = (int)Math.Pow(2, bits) - 1; - int mask = 0xFF >> (8 - bits); - int resultOffset = 0; - - foreach (byte b in bytes) - { - for (int shift = 0; shift < 8; shift += bits) - { - int colorIndex = (b >> (8 - bits - shift)) & mask; // * (255 / factor); - - result[resultOffset] = (byte)colorIndex; - - resultOffset++; - } - } - } - else - { - result = bytes; - } - - return result; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Common/Extensions/ComparableExtensions.cs b/src/ImageProcessorCore - Copy/Common/Extensions/ComparableExtensions.cs deleted file mode 100644 index cb0288fb7..000000000 --- a/src/ImageProcessorCore - Copy/Common/Extensions/ComparableExtensions.cs +++ /dev/null @@ -1,145 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 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. - /// - 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/ImageProcessorCore - Copy/Common/Extensions/EnumerableExtensions.cs b/src/ImageProcessorCore - Copy/Common/Extensions/EnumerableExtensions.cs deleted file mode 100644 index 107320412..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Common/Helpers/Guard.cs b/src/ImageProcessorCore - Copy/Common/Helpers/Guard.cs deleted file mode 100644 index 96c7023d4..000000000 --- a/src/ImageProcessorCore - Copy/Common/Helpers/Guard.cs +++ /dev/null @@ -1,192 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -// -// Provides methods to protect against invalid parameters. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("ImageProcessorCore.Tests")] -namespace ImageProcessorCore -{ - 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}."); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Common/Helpers/ImageMaths.cs b/src/ImageProcessorCore - Copy/Common/Helpers/ImageMaths.cs deleted file mode 100644 index 051b75f70..000000000 --- a/src/ImageProcessorCore - Copy/Common/Helpers/ImageMaths.cs +++ /dev/null @@ -1,289 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 < 0) - { - x = -x; - } - - temp = x * x; - if (x < 1) - { - x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b)); - return x / 6; - } - - if (x < 2) - { - x = ((-b - (6 * c)) * (x * temp)) + (((6 * b) + (30 * c)) * temp) + (((-12 * b) - (48 * c)) * x) + ((8 * b) + (24 * c)); - return x / 6; - } - - return 0; - } - - /// - /// 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 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) - { - const float Epsilon = .00001f; - int width = bitmap.Width; - int height = bitmap.Height; - Point topLeft = new Point(); - Point bottomRight = new Point(); - - Func delegateFunc; - - // Determine which channel to check against - switch (channel) - { - case RgbaComponent.R: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].R - b) > Epsilon; - break; - - case RgbaComponent.G: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].G - b) > Epsilon; - break; - - case RgbaComponent.A: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].A - b) > Epsilon; - break; - - default: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].B - b) > Epsilon; - break; - } - - Func 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 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 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 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/ImageProcessorCore - Copy/Filters/Alpha.cs b/src/ImageProcessorCore - Copy/Filters/Alpha.cs deleted file mode 100644 index 3532bb675..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Alpha.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the alpha component of the image. - /// - /// The image this method extends. - /// The new opacity of the image. Must be between 0 and 100. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Alpha(this Image source, int percent, ProgressEventHandler progressHandler = null) - { - return Alpha(source, percent, source.Bounds, progressHandler); - } - - /// - /// Alters the alpha component of the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Alpha(this Image source, int percent, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - AlphaProcessor processor = new AlphaProcessor(percent); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/BackgroundColor.cs b/src/ImageProcessorCore - Copy/Filters/BackgroundColor.cs deleted file mode 100644 index 98709cb32..000000000 --- a/src/ImageProcessorCore - Copy/Filters/BackgroundColor.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 image this method extends. - /// The color to set as the background. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image BackgroundColor(this Image source, Color color, ProgressEventHandler progressHandler = null) - { - BackgroundColorProcessor processor = new BackgroundColorProcessor(color); - processor.OnProgress += progressHandler; - - try - { - return source.Process(source.Bounds, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/BlackWhite.cs b/src/ImageProcessorCore - Copy/Filters/BlackWhite.cs deleted file mode 100644 index 98c3b7744..000000000 --- a/src/ImageProcessorCore - Copy/Filters/BlackWhite.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies black and white toning to the image. - /// - /// The image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image BlackWhite(this Image source, ProgressEventHandler progressHandler = null) - { - return BlackWhite(source, source.Bounds, progressHandler); - } - - /// - /// Applies black and white toning to the image. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image BlackWhite(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - BlackWhiteProcessor processor = new BlackWhiteProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Blend.cs b/src/ImageProcessorCore - Copy/Filters/Blend.cs deleted file mode 100644 index 77a94e3fa..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Blend.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 image this method extends. - /// - /// The image to blend with the currently processing image. - /// Disposal of this image is the responsibility of the developer. - /// - /// The opacity of the image image to blend. Must be between 0 and 100. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Blend(this Image source, ImageBase image, int percent = 50, ProgressEventHandler progressHandler = null) - { - return Blend(source, image, percent, source.Bounds, progressHandler); - } - - /// - /// 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. - /// Disposal of this image is the responsibility of the developer. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Blend(this Image source, ImageBase image, int percent, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - BlendProcessor processor = new BlendProcessor(image, percent); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/BoxBlur.cs b/src/ImageProcessorCore - Copy/Filters/BoxBlur.cs deleted file mode 100644 index 474f0d6e7..000000000 --- a/src/ImageProcessorCore - Copy/Filters/BoxBlur.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a box blur to the image. - /// - /// The image this method extends. - /// The 'radius' value representing the size of the area to sample. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image BoxBlur(this Image source, int radius = 7, ProgressEventHandler progressHandler = null) - { - return BoxBlur(source, radius, source.Bounds, progressHandler); - } - - /// - /// Applies a box blur to the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image BoxBlur(this Image source, int radius, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - BoxBlurProcessor processor = new BoxBlurProcessor(radius); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Brightness.cs b/src/ImageProcessorCore - Copy/Filters/Brightness.cs deleted file mode 100644 index 52944c801..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Brightness.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the brightness component of the image. - /// - /// The image this method extends. - /// The new brightness of the image. Must be between -100 and 100. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Brightness(this Image source, int amount, ProgressEventHandler progressHandler = null) - { - return Brightness(source, amount, source.Bounds, progressHandler); - } - - /// - /// Alters the brightness component of the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Brightness(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - BrightnessProcessor processor = new BrightnessProcessor(amount); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/ColorBlindness.cs b/src/ImageProcessorCore - Copy/Filters/ColorBlindness.cs deleted file mode 100644 index 78267b05e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/ColorBlindness.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies the given colorblindness simulator to the image. - /// - /// The image this method extends. - /// The type of color blindness simulator to apply. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness, ProgressEventHandler progressHandler = null) - { - return ColorBlindness(source, colorBlindness, source.Bounds, progressHandler); - } - - /// - /// Applies the given colorblindness simulator to the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - IImageProcessor processor; - - switch (colorBlindness) - { - case ImageProcessorCore.ColorBlindness.Achromatomaly: - processor = new AchromatomalyProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Achromatopsia: - processor = new AchromatopsiaProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Deuteranomaly: - processor = new DeuteranomalyProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Deuteranopia: - processor = new DeuteranopiaProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Protanomaly: - processor = new ProtanomalyProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Protanopia: - processor = new ProtanopiaProcessor(); - break; - - case ImageProcessorCore.ColorBlindness.Tritanomaly: - processor = new TritanomalyProcessor(); - break; - - default: - processor = new TritanopiaProcessor(); - break; - } - - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Contrast.cs b/src/ImageProcessorCore - Copy/Filters/Contrast.cs deleted file mode 100644 index cab12ca4e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Contrast.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the contrast component of the image. - /// - /// The image this method extends. - /// The new contrast of the image. Must be between -100 and 100. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Contrast(this Image source, int amount, ProgressEventHandler progressHandler = null) - { - return Contrast(source, amount, source.Bounds, progressHandler); - } - - /// - /// Alters the contrast component of the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Contrast(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - ContrastProcessor processor = new ContrastProcessor(amount); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/DetectEdges.cs b/src/ImageProcessorCore - Copy/Filters/DetectEdges.cs deleted file mode 100644 index ac3a0282d..000000000 --- a/src/ImageProcessorCore - Copy/Filters/DetectEdges.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Detects any edges within the image. Uses the filter - /// operating in greyscale mode. - /// - /// The image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image DetectEdges(this Image source, ProgressEventHandler progressHandler = null) - { - return DetectEdges(source, source.Bounds, new SobelProcessor { Greyscale = true }, progressHandler); - } - - /// - /// Detects any edges within the image. - /// - /// The image this method extends. - /// The filter for detecting edges. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image DetectEdges(this Image source, IEdgeDetectorFilter filter, ProgressEventHandler progressHandler = null) - { - return DetectEdges(source, source.Bounds, filter, progressHandler); - } - - /// - /// Detects any edges within the image. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The filter for detecting edges. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image DetectEdges(this Image source, Rectangle rectangle, IEdgeDetectorFilter filter, ProgressEventHandler progressHandler = null) - { - filter.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, filter); - } - finally - { - filter.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Greyscale.cs b/src/ImageProcessorCore - Copy/Filters/Greyscale.cs deleted file mode 100644 index 786a93576..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Greyscale.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies greyscale toning to the image. - /// - /// The image this method extends. - /// The formula to apply to perform the operation. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Greyscale(this Image source, GreyscaleMode mode = GreyscaleMode.Bt709, ProgressEventHandler progressHandler = null) - { - return Greyscale(source, source.Bounds, mode, progressHandler); - } - - /// - /// Applies greyscale toning to the image. - /// - /// 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. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Greyscale(this Image source, Rectangle rectangle, GreyscaleMode mode = GreyscaleMode.Bt709, ProgressEventHandler progressHandler = null) - { - IImageProcessor processor = mode == GreyscaleMode.Bt709 - ? (IImageProcessor)new GreyscaleBt709Processor() - : new GreyscaleBt601Processor(); - - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/GuassianBlur.cs b/src/ImageProcessorCore - Copy/Filters/GuassianBlur.cs deleted file mode 100644 index 646c6bdc0..000000000 --- a/src/ImageProcessorCore - Copy/Filters/GuassianBlur.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a Guassian blur to the image. - /// - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image GuassianBlur(this Image source, float sigma = 3f, ProgressEventHandler progressHandler = null) - { - return GuassianBlur(source, sigma, source.Bounds, progressHandler); - } - - /// - /// Applies a Guassian blur to the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image GuassianBlur(this Image source, float sigma, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - GuassianBlurProcessor processor = new GuassianBlurProcessor(sigma); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/GuassianSharpen.cs b/src/ImageProcessorCore - Copy/Filters/GuassianSharpen.cs deleted file mode 100644 index 06993070d..000000000 --- a/src/ImageProcessorCore - Copy/Filters/GuassianSharpen.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies a Guassian sharpening filter to the image. - /// - /// The image this method extends. - /// The 'sigma' value representing the weight of the blur. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image GuassianSharpen(this Image source, float sigma = 3f, ProgressEventHandler progressHandler = null) - { - return GuassianSharpen(source, sigma, source.Bounds, progressHandler); - } - - /// - /// Applies a Guassian sharpening filter to the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image GuassianSharpen(this Image source, float sigma, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - GuassianSharpenProcessor processor = new GuassianSharpenProcessor(sigma); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Hue.cs b/src/ImageProcessorCore - Copy/Filters/Hue.cs deleted file mode 100644 index 45a995c30..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Hue.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the hue component of the image. - /// - /// The image this method extends. - /// The angle in degrees to adjust the image. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Hue(this Image source, float degrees, ProgressEventHandler progressHandler = null) - { - return Hue(source, degrees, source.Bounds, progressHandler); - } - - /// - /// Alters the hue component of the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Hue(this Image source, float degrees, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - HueProcessor processor = new HueProcessor(degrees); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Invert.cs b/src/ImageProcessorCore - Copy/Filters/Invert.cs deleted file mode 100644 index eaeddfc62..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Invert.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Inverts the colors of the image. - /// - /// The image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Invert(this Image source, ProgressEventHandler progressHandler = null) - { - return Invert(source, source.Bounds, progressHandler); - } - - /// - /// Inverts the colors of the image. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Invert(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - InvertProcessor processor = new InvertProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Kodachrome.cs b/src/ImageProcessorCore - Copy/Filters/Kodachrome.cs deleted file mode 100644 index 3b4e3f1c6..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Kodachrome.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Kodachrome(this Image source, ProgressEventHandler progressHandler = null) - { - return Kodachrome(source, source.Bounds, progressHandler); - } - - /// - /// Alters the colors of the image recreating an old Kodachrome camera effect. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Kodachrome(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - KodachromeProcessor processor = new KodachromeProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Lomograph.cs b/src/ImageProcessorCore - Copy/Filters/Lomograph.cs deleted file mode 100644 index 5ecf0bcf4..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Lomograph.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Lomograph(this Image source, ProgressEventHandler progressHandler = null) - { - return Lomograph(source, source.Bounds, progressHandler); - } - - /// - /// Alters the colors of the image recreating an old Lomograph camera effect. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Lomograph(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - LomographProcessor processor = new LomographProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Options/ColorBlindness.cs b/src/ImageProcessorCore - Copy/Filters/Options/ColorBlindness.cs deleted file mode 100644 index 6d7fe849b..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// Enumerates the various types of color blindness. - /// - 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/ImageProcessorCore - Copy/Filters/Pixelate.cs b/src/ImageProcessorCore - Copy/Filters/Pixelate.cs deleted file mode 100644 index 6f86848d6..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Pixelate.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Pixelates and image with the given pixel size. - /// - /// The image this method extends. - /// The size of the pixels. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Pixelate(this Image source, int size = 4, ProgressEventHandler progressHandler = null) - { - return Pixelate(source, size, source.Bounds, progressHandler); - } - - /// - /// Pixelates and image with the given pixel size. - /// - /// The image this method extends. - /// The size of the pixels. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Pixelate(this Image source, int size, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - PixelateProcessor processor = new PixelateProcessor(size); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Polaroid.cs b/src/ImageProcessorCore - Copy/Filters/Polaroid.cs deleted file mode 100644 index 165f1d59a..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Polaroid.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Polaroid(this Image source, ProgressEventHandler progressHandler = null) - { - return Polaroid(source, source.Bounds, progressHandler); - } - - /// - /// Alters the colors of the image recreating an old Polaroid camera effect. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Polaroid(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - PolaroidProcessor processor = new PolaroidProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/AlphaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/AlphaProcessor.cs deleted file mode 100644 index 8ed703e03..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/AlphaProcessor.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the Alpha of an . - /// - public class AlphaProcessor : ImageProcessor - { - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float alpha = this.Value / 100f; - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Vector4 alphaVector = new Vector4(1, 1, 1, alpha); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Vector4 color = Color.ToNonPremultiplied(sourcePixels[x, y]).ToVector4(); - color *= alphaVector; - targetPixels[x, y] = Color.FromNonPremultiplied(new Color(color)); - } - - this.OnRowProcessed(); - } - }); - - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/BackgroundColorProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/BackgroundColorProcessor.cs deleted file mode 100644 index e78987d23..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/BackgroundColorProcessor.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Sets the background color of the image. - /// - public class BackgroundColorProcessor : ImageProcessor - { - /// - /// 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(Color color) - { - this.Value = Color.FromNonPremultiplied(color); - } - - /// - /// Gets the background color value. - /// - public Color Value { get; } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Color backgroundColor = this.Value; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Color color = sourcePixels[x, y]; - float a = color.A; - - if (a < 1 && a > 0) - { - color = Color.Lerp(color, backgroundColor, .5f); - } - - if (Math.Abs(a) < Epsilon) - { - color = backgroundColor; - } - - targetPixels[x, y] = color; - } - - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Binarization/ThresholdProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Binarization/ThresholdProcessor.cs deleted file mode 100644 index 60b49d0ee..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Binarization/ThresholdProcessor.cs +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// An to perform binary threshold filtering against an - /// . The image will be converted to greyscale before thresholding - /// occurs. - /// - public class ThresholdProcessor : ImageProcessor - { - /// - /// 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 ThresholdProcessor(float threshold) - { - Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); - this.Value = threshold; - } - - /// - /// Gets the threshold value. - /// - public float Value { get; } - - /// - /// The color to use for pixels that are above the threshold. - /// - public Color UpperColor => Color.White; - - /// - /// The color to use for pixels that fall below the threshold. - /// - public Color LowerColor => Color.Black; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - new GreyscaleBt709Processor().Apply(source, source, sourceRectangle); - } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float threshold = this.Value; - Color upper = this.UpperColor; - Color lower = this.LowerColor; - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Color color = sourcePixels[x, y]; - - // Any channel will do since it's greyscale. - targetPixels[x, y] = color.B >= threshold ? upper : lower; - } - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/BlendProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/BlendProcessor.cs deleted file mode 100644 index 5de0741fa..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/BlendProcessor.cs +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Threading.Tasks; - - /// - /// Combines two images together by blending the pixels. - /// - public class BlendProcessor : ImageProcessor - { - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Rectangle bounds = this.blend.Bounds; - float alpha = this.Value / 100f; - - using (PixelAccessor toBlendPixels = this.blend.Lock()) - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Color color = sourcePixels[x, y]; - - if (bounds.Contains(x, y)) - { - Color blendedColor = toBlendPixels[x, y]; - - if (blendedColor.A > 0) - { - // Lerping colors is dependent on the alpha of the blended color - float alphaFactor = alpha > 0 ? alpha : blendedColor.A; - color = Color.Lerp(color, blendedColor, alphaFactor); - } - } - - targetPixels[x, y] = color; - } - - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/BrightnessProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/BrightnessProcessor.cs deleted file mode 100644 index 6710ff593..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/BrightnessProcessor.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the brightness of an . - /// - public class BrightnessProcessor : ImageProcessor - { - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float brightness = this.Value / 100f; - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Color color = Color.Expand(sourcePixels[x, y]); - - Vector3 vector3 = color.ToVector3(); - vector3 += new Vector3(brightness); - - targetPixels[x, y] = Color.Compress(new Color(vector3, color.A)); - } - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs deleted file mode 100644 index 7fc3240d0..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/BlackWhiteProcessor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to their black and white equivalent. - /// - public class BlackWhiteProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs deleted file mode 100644 index d5740ec28..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatomalyProcessor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. - /// - public class AchromatomalyProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs deleted file mode 100644 index 6f2f7c269..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/AchromatopsiaProcessor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. - /// - public class AchromatopsiaProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs deleted file mode 100644 index fed09991f..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranomalyProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. - /// - public class DeuteranomalyProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs deleted file mode 100644 index 0ef190861..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/DeuteranopiaProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. - /// - public class DeuteranopiaProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs deleted file mode 100644 index b7152a68e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanomalyProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness. - /// - public class ProtanomalyProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs deleted file mode 100644 index 7984be139..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/ProtanopiaProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. - /// - public class ProtanopiaProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/README.md b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/README.md deleted file mode 100644 index 209f3b67b..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs deleted file mode 100644 index 618da36bb..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanomalyProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. - /// - public class TritanomalyProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs deleted file mode 100644 index e53de7a69..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorBlindness/TritanopiaProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. - /// - public class TritanopiaProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs deleted file mode 100644 index d27ea5c6d..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// The color matrix filter. - /// - public abstract class ColorMatrixFilter : ImageProcessor, IColorMatrixFilter - { - /// - public abstract Matrix4x4 Matrix { get; } - - /// - public virtual bool Compand => true; - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Matrix4x4 matrix = this.Matrix; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - for (int x = startX; x < endX; x++) - { - targetPixels[x, y] = this.ApplyMatrix(sourcePixels[x, y], matrix); - } - - this.OnRowProcessed(); - }); - } - } - - /// - /// Applies the color matrix against the given color. - /// - /// The source color. - /// The matrix. - /// - /// The . - /// - private Color ApplyMatrix(Color color, Matrix4x4 matrix) - { - bool compand = this.Compand; - - if (compand) - { - color = Color.Expand(color); - } - - Vector3 transformed = Vector3.Transform(color.ToVector3(), matrix); - return compand ? Color.Compress(new Color(transformed, color.A)) : new Color(transformed, color.A); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt601Processor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt601Processor.cs deleted file mode 100644 index b9a6daa6e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt601Processor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to greyscale applying the formula as specified by - /// ITU-R Recommendation BT.601 . - /// - public class GreyscaleBt601Processor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt709Processor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt709Processor.cs deleted file mode 100644 index 949e51e6a..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleBt709Processor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to greyscale applying the formula as specified by - /// ITU-R Recommendation BT.709 . - /// - public class GreyscaleBt709Processor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleMode.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleMode.cs deleted file mode 100644 index 269c1179e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/GreyscaleMode.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Provides enumeration over the various greyscale methods available. - /// - public enum GreyscaleMode - { - /// - /// ITU-R Recommendation BT.709 - /// - Bt709, - - /// - /// ITU-R Recommendation BT.601 - /// - Bt601 - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/HueProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/HueProcessor.cs deleted file mode 100644 index da7d4631c..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/HueProcessor.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - - public class HueProcessor : ColorMatrixFilter - { - /// - /// The used to alter the image. - /// - private Matrix4x4 matrix; - - /// - /// 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; - } - - /// - /// Gets the rotation value. - /// - public float Angle { get; } - - /// - public override Matrix4x4 Matrix => this.matrix; - - /// - public override bool Compand => false; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - float radians = (float)ImageMaths.DegreesToRadians(this.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; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs deleted file mode 100644 index 5a0c76684..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Encapsulates properties and methods for creating processors that utilize a matrix to - /// alter the image pixels. - /// - public interface IColorMatrixFilter : IImageProcessor - { - /// - /// Gets the used to alter the image. - /// - Matrix4x4 Matrix { get; } - - /// - /// Gets a value indicating whether to compress - /// or expand individual pixel colors the value on processing. - /// - bool Compand { get; } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/KodachromeProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/KodachromeProcessor.cs deleted file mode 100644 index 91c436460..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/KodachromeProcessor.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Kodachrome camera effect. - /// - public class KodachromeProcessor : ColorMatrixFilter - { - /// - 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/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/LomographProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/LomographProcessor.cs deleted file mode 100644 index 242299433..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/LomographProcessor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Lomograph effect. - /// - public class LomographProcessor : ColorMatrixFilter - { - /// - 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - new VignetteProcessor { Color = new Color(0, 10 / 255f, 0) }.Apply(target, target, targetRectangle); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/PolaroidProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/PolaroidProcessor.cs deleted file mode 100644 index ea6f85a39..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/PolaroidProcessor.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image recreating an old Polaroid effect. - /// - public class PolaroidProcessor : ColorMatrixFilter - { - /// - 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - new VignetteProcessor { Color = new Color(102 / 255f, 34 / 255f, 0) }.Apply(target, target, targetRectangle); - new GlowProcessor - { - Color = new Color(1, 153 / 255f, 102 / 255f, .7f), - RadiusX = target.Width / 4f, - RadiusY = target.Width / 4f - } - .Apply(target, target, targetRectangle); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SaturationProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SaturationProcessor.cs deleted file mode 100644 index abc00bfb6..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SaturationProcessor.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - - /// - /// An to change the saturation of an . - /// - public class SaturationProcessor : ColorMatrixFilter - { - /// - /// The saturation to be applied to the image. - /// - private readonly int saturation; - - /// - /// The used to alter the image. - /// - private Matrix4x4 matrix; - - /// - /// 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)); - this.saturation = saturation; - } - - /// - public override Matrix4x4 Matrix => this.matrix; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - float saturationFactor = this.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; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SepiaProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SepiaProcessor.cs deleted file mode 100644 index da6801311..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ColorMatrix/SepiaProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Converts the colors of the image to their sepia equivalent. - /// The formula used matches the svg specification. - /// - public class SepiaProcessor : ColorMatrixFilter - { - /// - 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; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/ContrastProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/ContrastProcessor.cs deleted file mode 100644 index 19f564be4..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/ContrastProcessor.cs +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to change the contrast of an . - /// - public class ContrastProcessor : ImageProcessor - { - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float contrast = (100f + this.Value) / 100f; - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Vector4 contrastVector = new Vector4(contrast, contrast, contrast, 1); - Vector4 shiftVector = new Vector4(.5f, .5f, .5f, 1); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Vector4 color = Color.Expand(sourcePixels[x, y]).ToVector4(); - color -= shiftVector; - color *= contrastVector; - color += shiftVector; - targetPixels[x, y] = Color.Compress(new Color(color)); - } - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/BoxBlurProcessor.cs deleted file mode 100644 index 042288ffd..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/BoxBlurProcessor.cs +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Applies a Box blur filter to the image. - /// - public class BoxBlurProcessor : Convolution2PassFilter - { - /// - /// The maximum size of the kernal in either direction. - /// - private readonly int kernelSize; - - /// - /// The vertical kernel - /// - private float[,] kernelY; - - /// - /// The horizontal kernel - /// - private float[,] kernelX; - - /// - /// 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; - } - - /// - public override float[,] KernelX => this.kernelX; - - /// - public override float[,] KernelY => this.kernelY; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.kernelY == null) - { - this.kernelY = this.CreateBoxKernel(false); - } - - if (this.kernelX == null) - { - this.kernelX = this.CreateBoxKernel(true); - } - } - - /// - /// 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, size] : new float[size, 1]; - 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, 0] = 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; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2DFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2DFilter.cs deleted file mode 100644 index b16a528db..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2DFilter.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Defines a filter that uses two one-dimensional matrices to perform convolution against an image. - /// - public abstract class Convolution2DFilter : ImageProcessor - { - /// - /// Gets the horizontal gradient operator. - /// - public abstract float[,] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public abstract float[,] KernelY { get; } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - float[,] kernelX = this.KernelX; - float[,] kernelY = this.KernelY; - int kernelYHeight = kernelY.GetLength(0); - int kernelYWidth = kernelY.GetLength(1); - int kernelXHeight = kernelX.GetLength(0); - int kernelXWidth = kernelX.GetLength(1); - 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, - 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); - - Color currentColor = sourcePixels[offsetX, offsetY]; - float r = currentColor.R; - float g = currentColor.G; - float b = currentColor.B; - - if (fy < kernelXHeight) - { - rX += kernelX[fy, fx] * r; - gX += kernelX[fy, fx] * g; - bX += kernelX[fy, fx] * b; - } - - if (fx < kernelYWidth) - { - rY += kernelY[fy, fx] * r; - gY += kernelY[fy, fx] * g; - bY += 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)); - - Color targetColor = targetPixels[x, y]; - targetPixels[x, y] = new Color(red, green, blue, targetColor.A); - } - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2PassFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2PassFilter.cs deleted file mode 100644 index c9031dfd7..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/Convolution2PassFilter.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Threading.Tasks; - - /// - /// Defines a filter that uses two one-dimensional matrices to perform two-pass convolution against an image. - /// - public abstract class Convolution2PassFilter : ImageProcessor - { - /// - /// Gets the horizontal gradient operator. - /// - public abstract float[,] KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public abstract float[,] KernelY { get; } - - /// - protected 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.GetLength(0); - int kernelWidth = kernel.GetLength(1); - 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, - y => - { - for (int x = startX; x < endX; x++) - { - Color destination = new Color(); - - // 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); - - Color currentColor = sourcePixels[offsetX, offsetY]; - destination += kernel[fy, fx] * currentColor; - } - } - - targetPixels[x, y] = destination; - } - - this.OnRowProcessed(); - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/ConvolutionFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/ConvolutionFilter.cs deleted file mode 100644 index 8ddcab4a5..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/ConvolutionFilter.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Threading.Tasks; - - /// - /// Defines a filter that uses a 2 dimensional matrix to perform convolution against an image. - /// - public abstract class ConvolutionFilter : ImageProcessor - { - /// - /// Gets the 2d gradient operator. - /// - public abstract float[,] KernelXY { get; } - - /// - protected 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, - 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); - - Color currentColor = sourcePixels[offsetX, offsetY]; - float r = currentColor.R; - float g = currentColor.G; - float b = currentColor.B; - - rX += kernelX[fy, fx] * r; - gX += kernelX[fy, fx] * g; - bX += kernelX[fy, fx] * b; - } - } - - float red = rX; - float green = gX; - float blue = bX; - - targetPixels[x, y] = new Color(red, green, blue); - } - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs deleted file mode 100644 index ce4aa0b2a..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Defines a filter that detects edges within an image using two - /// one-dimensional matrices. - /// - public abstract class EdgeDetector2DFilter : Convolution2DFilter, IEdgeDetectorFilter - { - /// - public bool Greyscale { get; set; } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.Greyscale) - { - new GreyscaleBt709Processor().Apply(source, source, sourceRectangle); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs deleted file mode 100644 index 7a18bb96b..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Defines a filter that detects edges within an image using a single - /// two dimensional matrix. - /// - public abstract class EdgeDetectorFilter : ConvolutionFilter, IEdgeDetectorFilter - { - /// - public bool Greyscale { get; set; } - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.Greyscale) - { - new GreyscaleBt709Processor().Apply(source, source, sourceRectangle); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs deleted file mode 100644 index b90f0d2ea..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Provides properties and methods allowing the detection of edges within an image. - /// - public interface IEdgeDetectorFilter : IImageProcessor - { - /// - /// Gets or sets a value indicating whether to convert the - /// image to greyscale before performing edge detection. - /// - bool Greyscale { get; set; } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs deleted file mode 100644 index 5af818241..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Kayyali operator filter. - /// - /// - public class KayyaliProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { 6, 0, -6 }, - { 0, 0, 0 }, - { -6, 0, 6 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { -6, 0, 6 }, - { 0, 0, 0 }, - { 6, 0, -6 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs deleted file mode 100644 index 24a561572..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Kirsch operator filter. - /// - /// - public class KirschProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { 5, 5, 5 }, - { -3, 0, -3 }, - { -3, -3, -3 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { 5, -3, -3 }, - { 5, 0, -3 }, - { 5, -3, -3 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs deleted file mode 100644 index a66d69253..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Laplacian 3 x 3 operator filter. - /// - /// - public class Laplacian3X3Processor : EdgeDetectorFilter - { - /// - public override float[,] KernelXY => new float[,] - { - { -1, -1, -1 }, - { -1, 8, -1 }, - { -1, -1, -1 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs deleted file mode 100644 index f2d3d885e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Laplacian 5 x 5 operator filter. - /// - /// - public class Laplacian5X5Processor : EdgeDetectorFilter - { - /// - public override float[,] KernelXY => new float[,] - { - { -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1 }, - { -1, -1, 24, -1, -1 }, - { -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs deleted file mode 100644 index 0aae3020a..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Laplacian of Gaussian operator filter. - /// - /// - public class LaplacianOfGaussianProcessor : EdgeDetectorFilter - { - /// - public override float[,] KernelXY => new float[,] - { - { 0, 0, -1, 0, 0 }, - { 0, -1, -2, -1, 0 }, - { -1, -2, 16, -2, -1 }, - { 0, -1, -2, -1, 0 }, - { 0, 0, -1, 0, 0 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs deleted file mode 100644 index 3a5bbe986..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Prewitt operator filter. - /// - /// - public class PrewittProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { -1, 0, 1 }, - { -1, 0, 1 }, - { -1, 0, 1 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { 1, 1, 1 }, - { 0, 0, 0 }, - { -1, -1, -1 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs deleted file mode 100644 index 0a6166418..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Roberts Cross operator filter. - /// - /// - public class RobertsCrossProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { 1, 0 }, - { 0, -1 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { 0, 1 }, - { -1, 0 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs deleted file mode 100644 index 80308a140..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Scharr operator filter. - /// - /// - public class ScharrProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { -3, 0, 3 }, - { -10, 0, 10 }, - { -3, 0, 3 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { 3, 10, 3 }, - { 0, 0, 0 }, - { -3, -10, -3 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs deleted file mode 100644 index 39f7d350d..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// The Sobel operator filter. - /// - /// - public class SobelProcessor : EdgeDetector2DFilter - { - /// - public override float[,] KernelX => new float[,] - { - { -1, 0, 1 }, - { -2, 0, 2 }, - { -1, 0, 1 } - }; - - /// - public override float[,] KernelY => new float[,] - { - { 1, 2, 1 }, - { 0, 0, 0 }, - { -1, -2, -1 } - }; - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianBlurProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianBlurProcessor.cs deleted file mode 100644 index 6288ea963..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianBlurProcessor.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - - /// - /// Applies a Gaussian blur filter to the image. - /// - public class GuassianBlurProcessor : Convolution2PassFilter - { - /// - /// The maximum size of the kernal in either direction. - /// - private readonly int kernelSize; - - /// - /// The spread of the blur. - /// - private readonly float sigma; - - /// - /// The vertical kernel - /// - private float[,] kernelY; - - /// - /// The horizontal kernel - /// - private float[,] kernelX; - - /// - /// 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; - } - - /// - /// 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; - } - - /// - /// 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; - } - - /// - public override float[,] KernelX => this.kernelX; - - /// - public override float[,] KernelY => this.kernelY; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.kernelY == null) - { - this.kernelY = this.CreateGaussianKernel(false); - } - - if (this.kernelX == null) - { - this.kernelX = this.CreateGaussianKernel(true); - } - } - - /// - /// 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, size] : new float[size, 1]; - 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, 0] = 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; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianSharpenProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianSharpenProcessor.cs deleted file mode 100644 index 9d70732d2..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/Convolution/GuassianSharpenProcessor.cs +++ /dev/null @@ -1,178 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - - /// - /// Applies a Gaussian sharpening filter to the image. - /// - public class GuassianSharpenProcessor : Convolution2PassFilter - { - /// - /// The maximum size of the kernal in either direction. - /// - private readonly int kernelSize; - - /// - /// The spread of the blur. - /// - private readonly float sigma; - - /// - /// The vertical kernel - /// - private float[,] kernelY; - - /// - /// The horizontal kernel - /// - private float[,] kernelX; - - /// - /// 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; - } - - /// - /// 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; - } - - /// - /// 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; - } - - /// - public override float[,] KernelX => this.kernelX; - - /// - public override float[,] KernelY => this.kernelY; - - /// - protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) - { - if (this.kernelY == null) - { - this.kernelY = this.CreateGaussianKernel(false); - } - - if (this.kernelX == null) - { - this.kernelX = this.CreateGaussianKernel(true); - } - } - - /// - /// 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, size] : new float[size, 1]; - 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, 0] = 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; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/GlowProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/GlowProcessor.cs deleted file mode 100644 index e046be6a9..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/GlowProcessor.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Creates a glow effect on the image - /// - public class GlowProcessor : ImageProcessor - { - /// - /// Gets or sets the glow color to apply. - /// - public Color Color { get; set; } = Color.White; - - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Color glowColor = this.Color; - Vector2 centre = Rectangle.Center(targetRectangle).ToVector2(); - float rX = this.RadiusX > 0 ? this.RadiusX : targetRectangle.Width / 2f; - float rY = this.RadiusY > 0 ? this.RadiusY : targetRectangle.Height / 2f; - float maxDistance = (float)Math.Sqrt(rX * rX + rY * rY); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - for (int x = startX; x < endX; x++) - { - float distance = Vector2.Distance(centre, new Vector2(x, y)); - Color sourceColor = sourcePixels[x, y]; - targetPixels[x, y] = Color.Lerp(glowColor, sourceColor, .5f * (distance / maxDistance)); - } - - this.OnRowProcessed(); - }); - } - } - } -} - diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/InvertProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/InvertProcessor.cs deleted file mode 100644 index 1f319b92b..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/InvertProcessor.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// An to invert the colors of an . - /// - public class InvertProcessor : ImageProcessor - { - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Vector3 inverseVector = Vector3.One; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x++) - { - Color color = sourcePixels[x, y]; - Vector3 vector = inverseVector - color.ToVector3(); - targetPixels[x, y] = new Color(vector, color.A); - } - - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/PixelateProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/PixelateProcessor.cs deleted file mode 100644 index 4769799b5..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/PixelateProcessor.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - - /// - /// An to invert the colors of an . - /// - public class PixelateProcessor : ImageProcessor - { - /// - /// 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; } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int sourceY = sourceRectangle.Y; - int sourceBottom = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int size = this.Value; - int offset = this.Value / 2; - - // Get the range on the y-plane to choose from. - IEnumerable range = EnumerableExtensions.SteppedRange(startY, i => i < endY, size); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.ForEach( - range, - y => - { - if (y >= sourceY && y < sourceBottom) - { - for (int x = startX; x < endX; x += size) - { - int offsetX = offset; - int offsetY = offset; - - // Make sure that the offset is within the boundary of the - // image. - while (y + offsetY >= sourceBottom) - { - offsetY--; - } - - while (x + offsetX >= endX) - { - offsetX--; - } - - // Get the pixel color in the centre of the soon to be pixelated area. - // ReSharper disable AccessToDisposedClosure - Color pixel = sourcePixels[x + offsetX, y + offsetY]; - - // For each pixel in the pixelate size, set it to the centre color. - for (int l = y; l < y + size && l < sourceBottom; l++) - { - for (int k = x; k < x + size && k < endX; k++) - { - targetPixels[k, l] = pixel; - } - } - } - - this.OnRowProcessed(); - } - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Processors/VignetteProcessor.cs b/src/ImageProcessorCore - Copy/Filters/Processors/VignetteProcessor.cs deleted file mode 100644 index 1fd4630ed..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Processors/VignetteProcessor.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Creates a vignette effect on the image - /// - public class VignetteProcessor : ImageProcessor - { - /// - /// Gets or sets the vignette color to apply. - /// - public Color Color { get; set; } = Color.Black; - - /// - /// 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 target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - Color vignetteColor = this.Color; - Vector2 centre = Rectangle.Center(targetRectangle).ToVector2(); - float rX = this.RadiusX > 0 ? this.RadiusX : targetRectangle.Width / 2f; - float rY = this.RadiusY > 0 ? this.RadiusY : targetRectangle.Height / 2f; - float maxDistance = (float)Math.Sqrt(rX * rX + rY * rY); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - for (int x = startX; x < endX; x++) - { - float distance = Vector2.Distance(centre, new Vector2(x, y)); - Color sourceColor = sourcePixels[x, y]; - targetPixels[x, y] = Color.Lerp(vignetteColor, sourceColor, 1 - .9f * distance / maxDistance); - } - this.OnRowProcessed(); - }); - } - } - } -} - diff --git a/src/ImageProcessorCore - Copy/Filters/Saturation.cs b/src/ImageProcessorCore - Copy/Filters/Saturation.cs deleted file mode 100644 index 93c69fe3e..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Saturation.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Alters the saturation component of the image. - /// - /// The image this method extends. - /// The new saturation of the image. Must be between -100 and 100. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Saturation(this Image source, int amount, ProgressEventHandler progressHandler = null) - { - return Saturation(source, amount, source.Bounds, progressHandler); - } - - /// - /// Alters the saturation component of the image. - /// - /// 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. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Saturation(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - SaturationProcessor processor = new SaturationProcessor(amount); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Filters/Sepia.cs b/src/ImageProcessorCore - Copy/Filters/Sepia.cs deleted file mode 100644 index 27d19b319..000000000 --- a/src/ImageProcessorCore - Copy/Filters/Sepia.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Applies sepia toning to the image. - /// - /// The image this method extends. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Sepia(this Image source, ProgressEventHandler progressHandler = null) - { - return Sepia(source, source.Bounds, progressHandler); - } - - /// - /// Applies sepia toning to the image. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Sepia(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) - { - SepiaProcessor processor = new SepiaProcessor(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(rectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpBitsPerPixel.cs deleted file mode 100644 index e7de3bc29..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Bmp/BmpCompression.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpCompression.cs deleted file mode 100644 index de3c66495..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoder.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoder.cs deleted file mode 100644 index 03d45f112..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoder.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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; - } - - /// - /// Decodes the image from the specified stream to the . - /// - /// The to decode to. - /// The containing image data. - public void Decode(Image image, Stream stream) - { - new BmpDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoderCore.cs deleted file mode 100644 index 9c2bc45b9..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpDecoderCore.cs +++ /dev/null @@ -1,445 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - using System.Threading.Tasks; - - /// - /// 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 type of pixels contained within the image. - /// The image, where the data should be set to. - /// Cannot be null (Nothing in Visual Basic). - /// The this._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 TPackedVector : IPackedVector, new() - { - 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) - { - // 255 * 4 - if (colorMapSize > 1020) - { - 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}'"); - } - - TPackedVector[] imageData = new TPackedVector[this.infoHeader.Width * this.infoHeader.Height]; - - 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(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel == 24) - { - this.ReadRgb24(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel == 16) - { - this.ReadRgb16(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); - } - else if (this.infoHeader.BitsPerPixel <= 8) - { - this.ReadRgbPalette( - imageData, - palette, - this.infoHeader.Width, - this.infoHeader.Height, - this.infoHeader.BitsPerPixel, - inverted); - } - - break; - default: - throw new NotSupportedException("Does not support this kind of bitmap files."); - } - - image.SetPixels(this.infoHeader.Width, this.infoHeader.Height, imageData); - } - 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. - /// 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; - } - - /// - /// Reads the color palette from the stream. - /// - /// The image data 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. - private void ReadRgbPalette(float[] imageData, byte[] colors, int width, int height, int bits, bool inverted) - { - // Pixels per byte (bits per pixel) - int ppb = 8 / bits; - - int arrayWidth = (width + ppb - 1) / ppb; - - // Bit mask - int mask = 0xFF >> (8 - bits); - - byte[] data = new byte[arrayWidth * height]; - - this.currentStream.Read(data, 0, data.Length); - - // Rows are aligned on 4 byte boundaries - int alignment = arrayWidth % 4; - if (alignment != 0) - { - alignment = 4 - alignment; - } - - Parallel.For( - 0, - height, - y => - { - int rowOffset = y * (arrayWidth + alignment); - - for (int x = 0; x < arrayWidth; x++) - { - int offset = rowOffset + x; - - // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height, inverted); - - int colOffset = x * ppb; - - for (int shift = 0; shift < ppb && (colOffset + shift) < width; shift++) - { - int colorIndex = ((data[offset] >> (8 - bits - (shift * bits))) & mask) * 4; - int arrayOffset = ((row * width) + (colOffset + shift)) * 4; - - // We divide by 255 as we will store the colors in our floating point format. - // Stored in r-> g-> b-> a order. - imageData[arrayOffset] = colors[colorIndex + 2] / 255f; // r - imageData[arrayOffset + 1] = colors[colorIndex + 1] / 255f; // g - imageData[arrayOffset + 2] = colors[colorIndex] / 255f; // b - imageData[arrayOffset + 3] = 1; // a - } - } - }); - } - - /// - /// Reads the 16 bit color palette from the stream - /// - /// The type of pixels contained within the image. - /// The image data to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - private void ReadRgb16(TPackedVector[] imageData, int width, int height, bool inverted) - where TPackedVector : IPackedVector, new() - { - // 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 - - int alignment; - byte[] data = this.GetImageArray(width, height, 2, out alignment); - - Parallel.For( - 0, - height, - y => - { - int rowOffset = y * ((width * 2) + alignment); - - // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height, inverted); - - for (int x = 0; x < width; x++) - { - int offset = rowOffset + (x * 2); - - short temp = BitConverter.ToInt16(data, offset); - - byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR); - byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG); - byte b = (byte)((temp & Rgb16BMask) * ScaleR); - - int arrayOffset = ((row * width) + x); - - // Stored in b-> g-> r-> a order. - TPackedVector packed = new TPackedVector(); - packed.PackBytes(b, g, r, 255); - imageData[arrayOffset] = packed; - } - }); - } - - /// - /// Reads the 24 bit color palette from the stream - /// - /// The type of pixels contained within the image. - /// The image data to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - private void ReadRgb24(TPackedVector[] imageData, int width, int height, bool inverted) - where TPackedVector : IPackedVector, new() - { - int alignment; - byte[] data = this.GetImageArray(width, height, 3, out alignment); - - Parallel.For( - 0, - height, - y => - { - int rowOffset = y * ((width * 3) + alignment); - - // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height, inverted); - - for (int x = 0; x < width; x++) - { - int offset = rowOffset + (x * 3); - int arrayOffset = ((row * width) + x); - - // We divide by 255 as we will store the colors in our floating point format. - // Stored in b-> g-> r-> a order. - TPackedVector packed = new TPackedVector(); - packed.PackBytes(data[offset], data[offset + 1], data[offset + 2], 255); - imageData[arrayOffset] = packed; - } - }); - } - - /// - /// Reads the 32 bit color palette from the stream - /// - /// The type of pixels contained within the image. - /// The image data to assign the palette to. - /// The width of the bitmap. - /// The height of the bitmap. - private void ReadRgb32(TPackedVector[] imageData, int width, int height, bool inverted) - where TPackedVector : IPackedVector, new() - { - int alignment; - byte[] data = this.GetImageArray(width, height, 4, out alignment); - - Parallel.For( - 0, - height, - y => - { - int rowOffset = y * ((width * 4) + alignment); - - // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height, inverted); - - for (int x = 0; x < width; x++) - { - int offset = rowOffset + (x * 4); - int arrayOffset = ((row * width) + x); - - // Stored in b-> g-> r-> a order. - TPackedVector packed = new TPackedVector(); - packed.PackBytes(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]); - imageData[arrayOffset] = packed; - } - }); - } - - /// - /// Returns a containing the pixels for the current bitmap. - /// - /// The width of the bitmap. - /// The height. - /// The number of bytes per pixel. - /// The alignment of the pixels. - /// - /// The containing the pixels. - /// - private byte[] GetImageArray(int width, int height, int bytes, out int alignment) - { - int dataWidth = width; - - alignment = (width * bytes) % 4; - - if (alignment != 0) - { - alignment = 4 - alignment; - } - - int size = ((dataWidth * bytes) + alignment) * height; - - byte[] data = new byte[size]; - - this.currentStream.Read(data, 0, size); - - return data; - } - - /// - /// 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/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoder.cs deleted file mode 100644 index 4b212d4ea..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoder.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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(ImageBase image, Stream stream) - where TPackedVector: IPackedVector - { - BmpEncoderCore encoder = new BmpEncoderCore(); - encoder.Encode(image, stream, this.BitsPerPixel); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoderCore.cs deleted file mode 100644 index 2ad8e24e6..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpEncoderCore.cs +++ /dev/null @@ -1,205 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - - using 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. - internal sealed class BmpEncoderCore - { - /// - /// The number of bits per pixel. - /// - private BmpBitsPerPixel bmpBitsPerPixel; - - /// - /// Encodes the image to the specified stream from the . - /// - /// The type of pixels contained within the image. - /// The to encode from. - /// The to encode the image data to. - /// The - public void Encode(ImageBase image, Stream stream, BmpBitsPerPixel bitsPerPixel) - where TPackedVector : IPackedVector - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - this.bmpBitsPerPixel = bitsPerPixel; - - int rowWidth = image.Width; - - // TODO: Check this for varying file formats. - int amount = (image.Width * (int)this.bmpBitsPerPixel) % 4; - if (amount != 0) - { - rowWidth += 4 - amount; - } - - // Do not use IDisposable pattern here as we want to preserve the stream. - EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Little, stream); - - int bpp = (int)this.bmpBitsPerPixel; - - BmpFileHeader fileHeader = new BmpFileHeader - { - Type = 19778, // BM - Offset = 54, - FileSize = 54 + (image.Height * rowWidth * bpp) - }; - - BmpInfoHeader infoHeader = new BmpInfoHeader - { - HeaderSize = 40, - Height = image.Height, - Width = image.Width, - BitsPerPixel = (short)(8 * bpp), - Planes = 1, - ImageSize = image.Height * rowWidth * bpp, - ClrUsed = 0, - ClrImportant = 0 - }; - - 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 type of pixels contained within the image. - /// - /// The containing the stream to write to. - /// - /// - /// The containing pixel data. - /// - private void WriteImage(EndianBinaryWriter writer, ImageBase image) - where TPackedVector : IPackedVector - { - // TODO: Add more compression formats. - int amount = (image.Width * (int)this.bmpBitsPerPixel) % 4; - if (amount != 0) - { - amount = 4 - amount; - } - - using (IPixelAccessor pixels = image.Lock()) - { - switch (this.bmpBitsPerPixel) - { - case BmpBitsPerPixel.Pixel32: - this.Write32bit(writer, pixels, amount); - break; - - case BmpBitsPerPixel.Pixel24: - this.Write24bit(writer, pixels, amount); - break; - } - } - } - - /// - /// Writes the 32bit color palette to the stream. - /// - /// The containing the stream to write to. - /// The containing pixel data. - /// The amount to pad each row by. - private void Write32bit(EndianBinaryWriter writer, IPixelAccessor pixels, int amount) - { - for (int y = pixels.Height - 1; y >= 0; y--) - { - for (int x = 0; x < pixels.Width; x++) - { - // Convert back to b-> g-> r-> a order. - byte[] bytes = pixels[x, y].ToBytes(); - writer.Write(bytes); - } - - // Pad - for (int i = 0; i < amount; i++) - { - writer.Write((byte)0); - } - } - } - - /// - /// Writes the 24bit color palette to the stream. - /// - /// The containing the stream to write to. - /// The containing pixel data. - /// The amount to pad each row by. - private void Write24bit(EndianBinaryWriter writer, IPixelAccessor pixels, int amount) - { - for (int y = pixels.Height - 1; y >= 0; y--) - { - for (int x = 0; x < pixels.Width; x++) - { - // Convert back to b-> g-> r-> a order. - byte[] bytes = pixels[x, y].ToBytes(); - writer.Write(new[] { bytes[0], bytes[1], bytes[2] }); - } - - // Pad - for (int i = 0; i < amount; i++) - { - writer.Write((byte)0); - } - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Bmp/BmpFileHeader.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpFileHeader.cs deleted file mode 100644 index 6f626ee70..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Bmp/BmpFormat.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpFormat.cs deleted file mode 100644 index 6f640c4b9..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Bmp/BmpInfoHeader.cs b/src/ImageProcessorCore - Copy/Formats/Bmp/BmpInfoHeader.cs deleted file mode 100644 index c21a52d21..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Bmp/README.md b/src/ImageProcessorCore - Copy/Formats/Bmp/README.md deleted file mode 100644 index d07283843..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Formats/Gif/BitEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Gif/BitEncoder.cs deleted file mode 100644 index a0c633a19..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/BitEncoder.cs +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System.Collections.Generic; - - /// - /// Handles the encoding of bits for compression. - /// - internal class BitEncoder - { - /// - /// The inner list for collecting the bits. - /// - private readonly List list = new List(); - - /// - /// The current working bit. - /// - private int currentBit; - - /// - /// The current value. - /// - private int currentValue; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The initial bits. - /// - public BitEncoder(int initial) - { - this.IntitialBit = initial; - } - - /// - /// Gets or sets the intitial bit. - /// - public int IntitialBit { get; set; } - - /// - /// The number of bytes in the encoder. - /// - public int Length => this.list.Count; - - /// - /// Adds the current byte to the end of the encoder. - /// - /// - /// The byte to add. - /// - public void Add(int item) - { - this.currentValue |= item << this.currentBit; - - this.currentBit += this.IntitialBit; - - while (this.currentBit >= 8) - { - byte value = (byte)(this.currentValue & 0XFF); - this.currentValue = this.currentValue >> 8; - this.currentBit -= 8; - this.list.Add(value); - } - } - - /// - /// Adds the collection of bytes to the end of the encoder. - /// - /// - /// The collection of bytes to add. - /// The collection itself cannot be null but can contain elements that are null. - public void AddRange(byte[] collection) - { - this.list.AddRange(collection); - } - - /// - /// Copies a range of elements from the encoder to a compatible one-dimensional array, - /// starting at the specified index of the target array. - /// - /// - /// The zero-based index in the source at which copying begins. - /// - /// - /// The one-dimensional Array that is the destination of the elements copied - /// from . The Array must have zero-based indexing - /// - /// The zero-based index in array at which copying begins. - /// The number of bytes to copy. - public void CopyTo(int index, byte[] array, int arrayIndex, int count) - { - this.list.CopyTo(index, array, arrayIndex, count); - } - - /// - /// Removes all the bytes from the encoder. - /// - public void Clear() - { - this.list.Clear(); - } - - /// - /// Copies the bytes into a new array. - /// - /// - public byte[] ToArray() - { - return this.list.ToArray(); - } - - /// - /// The end. - /// - internal void End() - { - while (this.currentBit > 0) - { - byte value = (byte)(this.currentValue & 0XFF); - this.currentValue = this.currentValue >> 8; - this.currentBit -= 8; - this.list.Add(value); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Gif/DisposalMethod.cs b/src/ImageProcessorCore - Copy/Formats/Gif/DisposalMethod.cs deleted file mode 100644 index 4b0a01973..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Gif/GifConstants.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifConstants.cs deleted file mode 100644 index 42949cf16..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Gif/GifDecoder.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifDecoder.cs deleted file mode 100644 index 1abbcb2fb..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/GifDecoder.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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 - } - - /// - /// Decodes the image from the specified stream to the . - /// - /// The to decode to. - /// The containing image data. - public void Decode(Image image, Stream stream) - { - new GifDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Gif/GifDecoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifDecoderCore.cs deleted file mode 100644 index 693f974c7..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/GifDecoderCore.cs +++ /dev/null @@ -1,428 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - - /// - /// Performs the gif decoding operation. - /// - internal class GifDecoderCore - { - /// - /// 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 float[] 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.Seek(6, SeekOrigin.Current); - 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 > ImageBase.MaxWidth || this.logicalScreenDescriptor.Height > ImageBase.MaxHeight) - { - throw new ArgumentOutOfRangeException( - $"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{ImageBase.MaxWidth}x{ImageBase.MaxHeight}'"); - } - } - - /// - /// Skips the designated number of bytes in the stream. - /// - /// The number of bytes to skip. - private void Skip(int length) - { - this.currentStream.Seek(length, SeekOrigin.Current); - - int flag; - - while ((flag = this.currentStream.ReadByte()) != 0) - { - this.currentStream.Seek(flag, SeekOrigin.Current); - } - } - - /// - /// 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 float[imageWidth * imageHeight * 4]; - } - - float[] lastFrame = null; - - if (this.graphicsControlExtension != null && - this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) - { - lastFrame = new float[imageWidth * imageHeight * 4]; - - 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) * 4; - int index = indices[i]; - - if (this.graphicsControlExtension == null || - this.graphicsControlExtension.TransparencyFlag == false || - this.graphicsControlExtension.TransparencyIndex != index) - { - // We divide by 255 as we will store the colors in our floating point format. - // Stored in r-> g-> b-> a order. - // Gifs don't store alpha transparency so we don't need to convert to - // premultiplied. - int indexOffset = index * 3; - this.currentFrame[offset + 0] = colorTable[indexOffset] / 255f; // r - this.currentFrame[offset + 1] = colorTable[indexOffset + 1] / 255f; // g - this.currentFrame[offset + 2] = colorTable[indexOffset + 2] / 255f; // b - this.currentFrame[offset + 3] = 1; // a - } - - i++; - } - } - - float[] pixels = new float[imageWidth * imageHeight * 4]; - - 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) * 4; - - // Stored in r-> g-> b-> a order. - this.currentFrame[offset] = 0; - this.currentFrame[offset + 1] = 0; - this.currentFrame[offset + 2] = 0; - this.currentFrame[offset + 3] = 0; - } - } - } - else if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) - { - this.currentFrame = lastFrame; - } - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoder.cs deleted file mode 100644 index 7a1c81c2b..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoder.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - - using ImageProcessorCore.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; - - /// - /// 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(ImageBase image, Stream stream) - { - GifEncoderCore encoder = new GifEncoderCore - { - Quality = this.Quality, - Quantizer = this.Quantizer, - Threshold = this.Threshold - }; - - encoder.Encode(image, stream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoderCore.cs deleted file mode 100644 index c4846c44f..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/GifEncoderCore.cs +++ /dev/null @@ -1,289 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - using System.Linq; - using System.Threading.Tasks; - - using ImageProcessorCore.IO; - using ImageProcessorCore.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; - - /// - /// The quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Encodes the image to the specified stream from the . - /// - /// The to encode from. - /// The to encode the image data to. - public void Encode(ImageBase imageBase, Stream stream) - { - Guard.NotNull(imageBase, nameof(imageBase)); - Guard.NotNull(stream, nameof(stream)); - - Image image = (Image)imageBase; - - if (this.Quantizer == null) - { - this.Quantizer = new OctreeQuantizer { Threshold = this.Threshold }; - } - - // 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 : imageBase.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 = this.Quantizer.Quantize(image, this.Quality); - - // Write the header. - this.WriteHeader(writer); - - // Write the LSD. We'll use local color tables for now. - this.WriteLogicalScreenDescriptor(image, writer, quantized.TransparentIndex); - - // Write the first frame. - this.WriteGraphicalControlExtension(imageBase, writer, quantized.TransparentIndex); - 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 = this.Quantizer.Quantize(frame, this.Quality); - this.WriteGraphicalControlExtension(frame, writer, quantizedFrame.TransparentIndex); - this.WriteImageDescriptor(frame, writer); - this.WriteColorTable(quantizedFrame, writer); - this.WriteImageData(quantizedFrame, writer); - } - } - - // TODO: Write Comments extension etc - writer.Write(GifConstants.EndIntroducer); - } - - /// - /// 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 image to encode. - /// The writer to write to the stream with. - /// The transparency index to set the default backgound index to. - private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int tranparencyIndex) - { - 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 = new 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 exstension to the stream. - /// - /// The writer to write to the stream with. - /// The animated image repeat count. - /// Th 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 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) - { - // 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 = new 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 to be encoded. - /// The stream to write to. - private void WriteImageDescriptor(ImageBase image, EndianBinaryWriter writer) - { - 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 = new 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 to encode. - /// The writer to write to the stream with. - private void WriteColorTable(QuantizedImage image, EndianBinaryWriter writer) - { - // Grab the palette and write it to the stream. - Bgra32[] 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; - Bgra32 color = palette[i]; - - 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 containing indexed pixels. - /// The stream to write to. - private void WriteImageData(QuantizedImage image, EndianBinaryWriter writer) - { - byte[] indexedPixels = image.Pixels; - - LzwEncoder encoder = new LzwEncoder(indexedPixels, (byte)this.bitDepth); - encoder.Encode(writer.BaseStream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Gif/GifFormat.cs b/src/ImageProcessorCore - Copy/Formats/Gif/GifFormat.cs deleted file mode 100644 index 572815630..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Gif/LzwDecoder.cs b/src/ImageProcessorCore - Copy/Formats/Gif/LzwDecoder.cs deleted file mode 100644 index 75d590673..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/LzwDecoder.cs +++ /dev/null @@ -1,231 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - 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/ImageProcessorCore - Copy/Formats/Gif/LzwEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Gif/LzwEncoder.cs deleted file mode 100644 index a9681d2c5..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/LzwEncoder.cs +++ /dev/null @@ -1,385 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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 int curPixel; - - /// - /// Number of bits/code - /// - private int bitCount; - - /// - /// User settable max # bits/code - /// - private int maxbits = Bits; - - private int maxcode; // maximum code, given bitCount - - private int maxmaxcode = 1 << Bits; // should NEVER generate this code - - private readonly int[] hashTable = new int[HashSize]; - - private readonly int[] codeTable = new int[HashSize]; - - /// - /// 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; - - private readonly int[] masks = - { - 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF - }; - - /// - /// Number of characters so far in this 'packet' - /// - private int accumulatorCount; - - /// - /// Define the storage for the packet accumulator. - /// - private readonly byte[] accumulators = new byte[256]; - - /// - /// 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.curPixel = 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 inital 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 - private void FlushPacket(Stream outs) - { - if (this.accumulatorCount > 0) - { - outs.WriteByte((byte)this.accumulatorCount); - outs.Write(this.accumulators, 0, this.accumulatorCount); - this.accumulatorCount = 0; - } - } - - /// - /// Return the next pixel from the image - /// - /// - /// The - /// - private int NextPixel() - { - if (this.curPixel == this.pixelArray.Length) - { - return Eof; - } - - if (this.curPixel == this.pixelArray.Length) - return Eof; - - this.curPixel++; - return this.pixelArray[this.curPixel - 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/ImageProcessorCore - Copy/Formats/Gif/PackedField.cs b/src/ImageProcessorCore - Copy/Formats/Gif/PackedField.cs deleted file mode 100644 index 0141d36c6..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Gif/PackedField.cs +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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 = new 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/ImageProcessorCore - Copy/Formats/Gif/README.md b/src/ImageProcessorCore - Copy/Formats/Gif/README.md deleted file mode 100644 index d47a4c683..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Formats/Gif/Sections/GifGraphicsControlExtension.cs b/src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifGraphicsControlExtension.cs deleted file mode 100644 index 071dc62c8..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Gif/Sections/GifImageDescriptor.cs b/src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifImageDescriptor.cs deleted file mode 100644 index 62737de66..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs b/src/ImageProcessorCore - Copy/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs deleted file mode 100644 index 8c0400f24..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/IImageDecoder.cs b/src/ImageProcessorCore - Copy/Formats/IImageDecoder.cs deleted file mode 100644 index 0f3a8504c..000000000 --- a/src/ImageProcessorCore - Copy/Formats/IImageDecoder.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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 type of pixels contained within the image. - /// The to decode to. - /// The containing image data. - void Decode(Image image, Stream stream) where TPackedVector : IPackedVector; - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/IImageEncoder.cs b/src/ImageProcessorCore - Copy/Formats/IImageEncoder.cs deleted file mode 100644 index df7234aad..000000000 --- a/src/ImageProcessorCore - Copy/Formats/IImageEncoder.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates properties and methods required for decoding an image to a stream. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore.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 type of pixels contained within the image. - /// The to encode from. - /// The to encode the image data to. - void Encode(ImageBase image, Stream stream) where TPackedVector : IPackedVector; - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/IImageFormat.cs b/src/ImageProcessorCore - Copy/Formats/IImageFormat.cs deleted file mode 100644 index 62b4b7891..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Jpg/Block.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/Block.cs deleted file mode 100644 index 35aa10f18..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/Block.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// Represents an 8x8 block of coefficients to transform and encode. - /// - internal class Block - { - /// - /// Gets the size of the block. - /// - public const int BlockSize = 64; - - /// - /// The array of block data. - /// - private readonly int[] data; - - /// - /// Initializes a new instance of the class. - /// - public Block() - { - this.data = new int[BlockSize]; - } - - /// - /// Gets the pixel data at the given block index. - /// - /// The index of the data to return. - /// - /// The . - /// - public int this[int index] - { - get { return this.data[index]; } - set { this.data[index] = value; } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Jpg/FDCT.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/FDCT.cs deleted file mode 100644 index e51ea6415..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/FDCT.cs +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// Performs a fast, forward descrete 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. - public static void Transform(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/ImageProcessorCore - Copy/Formats/Jpg/IDCT.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/IDCT.cs deleted file mode 100644 index 7542f4d38..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/IDCT.cs +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - 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) - - // idct 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. - public static void Transform(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/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoder.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoder.cs deleted file mode 100644 index 89aa4e001..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoder.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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; - } - - /// - /// Decodes the image from the specified stream and sets - /// the data to image. - /// - /// 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 (Nothing in Visual Basic). - /// - or - - /// is null (Nothing in Visual Basic). - /// - public void Decode(Image image, Stream stream) - { - Guard.NotNull(image, "image"); - Guard.NotNull(stream, "stream"); - - JpegDecoderCore decoder = new JpegDecoderCore(); - decoder.Decode(stream, image, 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/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id deleted file mode 100644 index a5c139745..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -7a5076971068e0f389da2fb1e8b25216f4049718 \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoder.cs deleted file mode 100644 index 32c4d5f28..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoder.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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(ImageBase image, Stream stream) - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - JpegEncoderCore encode = new JpegEncoderCore(); - if (this.subsampleSet) - { - encode.Encode(stream, image, this.Quality, this.Subsample); - } - else - { - encode.Encode(stream, image, this.Quality, this.Quality >= 80 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoderCore.cs deleted file mode 100644 index 384f18b36..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegEncoderCore.cs +++ /dev/null @@ -1,783 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - - internal class JpegEncoderCore - { - /// - /// 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, - }; - - private const int NQuantIndex = 2; - - /// - /// Counts the number of bits needed to hold an integer. - /// - private readonly byte[] bitCount = - { - 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, - } - }; - - /// - /// The Huffman encoding specifications. - /// This encoder uses the same Huffman encoding for all images. - /// - private readonly HuffmanSpec[] theHuffmanSpec = { - // 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, - }) - }; - - /// - /// 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 - { - public readonly uint[] Values; - - public HuffmanLut(HuffmanSpec s) - { - int maxValue = 0; - - foreach (var v in s.Values) - { - if (v > maxValue) maxValue = v; - } - - this.Values = new uint[maxValue + 1]; - - int code = 0; - int k = 0; - - for (int i = 0; i < s.Count.Length; i++) - { - int nBits = (i + 1) << 24; - for (int j = 0; j < s.Count[i]; j++) - { - this.Values[s.Values[k]] = (uint)(nBits | code); - code++; - k++; - } - - code <<= 1; - } - } - } - - // w is the writer to write to. err is the first error encountered during - // writing. All attempted writes after the first error become no-ops. - private Stream outputStream; - - /// - /// A scratch buffer to reduce allocations. - /// - private readonly byte[] buffer = new byte[16]; - - /// - /// The accumulated bits to write to the stream. - /// - private uint bits; - - /// - /// The accumulated bits to write to the stream. - /// - private uint nBits; - - /// - /// The scaled quantization tables, in zig-zag order. - /// - private readonly byte[][] quant = new byte[NQuantIndex][]; // [Block.blockSize]; - - // The compiled representations of theHuffmanSpec. - private readonly HuffmanLut[] theHuffmanLUT = new HuffmanLut[4]; - - /// - /// The subsampling method to use. - /// - private JpegSubsample subsample; - - /// - /// Writes the given byte to the stream. - /// - /// - private void WriteByte(byte b) - { - var data = new byte[1]; - data[0] = b; - this.outputStream.Write(data, 0, 1); - } - - /// - /// Emits the least significant nBits bits of bits to the bit-stream. - /// The precondition is bits < 1<<nBits && nBits <= 16. - /// - /// - /// - private void Emit(uint bits, uint nBits) - { - nBits += this.nBits; - bits <<= (int)(32 - nBits); - bits |= this.bits; - while (nBits >= 8) - { - byte b = (byte)(bits >> 24); - this.WriteByte(b); - if (b == 0xff) this.WriteByte(0x00); - bits <<= 8; - nBits -= 8; - } - - this.bits = bits; - this.nBits = nBits; - } - - /// - /// 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 = this.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.bitCount[a]; - } - else - { - bt = 8 + (uint)this.bitCount[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. - /// - private int WriteBlock(Block block, QuantIndex index, int prevDC) - { - FDCT.Transform(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. - var 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; - } - - // toYCbCr converts the 8x8 region of m whose top-left corner is p to its - // YCbCr values. - private void ToYCbCr(PixelAccessor pixels, int x, int y, Block yBlock, Block cbBlock, Block crBlock) - { - int xmax = pixels.Width - 1; - int ymax = pixels.Height - 1; - for (int j = 0; j < 8; j++) - { - for (int i = 0; i < 8; i++) - { - YCbCr color = pixels[Math.Min(x + i, xmax), Math.Min(y + j, ymax)]; - int index = (8 * j) + i; - yBlock[index] = (int)color.Y; - cbBlock[index] = (int)color.Cb; - crBlock[index] = (int)color.Cr; - } - } - } - - /// - /// Scales the 16x16 region represented by the 4 src blocks to the 8x8 - /// dst block. - /// - /// The destination block array - /// The source block array. - private void Scale16X16_8X8(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; - } - } - } - } - - // The SOS marker "\xff\xda" followed by 8 bytes: - // - the marker length "\x00\x08", - // - the number of components "\x01", - // - component 1 uses DC table 0 and AC table 0 "\x01\x00", - // - 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[] SOSHeaderY = - { - JpegConstants.Markers.XFF, JpegConstants.Markers.SOS, - 0x00, 0x08, // Length (high byte, low byte), must be 6 + 2 * (number of components in scan) - 0x01, // Number of components in a scan, 1 - 0x01, // Component Id Y - 0x00, // 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 SOS 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, - 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) - }; - - // Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given - // options. Default parameters are used if a nil *Options is passed. - public void Encode(Stream stream, ImageBase image, int quality, JpegSubsample sample) - { - 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; - - // TODO: This should be static should it not? - for (int i = 0; i < this.theHuffmanSpec.Length; i++) - { - this.theHuffmanLUT[i] = new HuffmanLut(this.theHuffmanSpec[i]); - } - - for (int i = 0; i < NQuantIndex; 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 < NQuantIndex; 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. - // TODO: JFIF header etc. - this.buffer[0] = 0xff; - this.buffer[1] = 0xd8; - stream.Write(this.buffer, 0, 2); - - // Write the quantization tables. - this.WriteDQT(); - - // Write the image dimensions. - this.WriteSOF0(image.Width, image.Height, componentCount); - - // Write the Huffman tables. - this.WriteDHT(componentCount); - - // Write the image data. - using (PixelAccessor pixels = image.Lock()) - { - this.WriteSOS(pixels); - } - - // Write the End Of Image marker. - this.buffer[0] = 0xff; - this.buffer[1] = 0xd9; - 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); - } - - /// - /// Writes the Define Quantization Marker and tables. - /// - private void WriteDQT() - { - int markerlen = 2 + NQuantIndex * (1 + Block.BlockSize); - this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen); - for (int i = 0; i < NQuantIndex; i++) - { - this.WriteByte((byte)i); - this.outputStream.Write(this.quant[i], 0, this.quant[i].Length); - } - } - - /// - /// Writes the Start Of Frame (Baseline) marker - /// - /// The width of the image - /// The height of the image - /// - private void WriteSOF0(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 = grey 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 WriteDHT(int nComponent) - { - byte[] headers = { 0x00, 0x10, 0x01, 0x11 }; - int markerlen = 2; - HuffmanSpec[] specs = this.theHuffmanSpec; - - if (nComponent == 1) - { - // Drop the Chrominance tables. - specs = new[] { this.theHuffmanSpec[0], this.theHuffmanSpec[1] }; - } - - foreach (var 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]; - - this.WriteByte(headers[i]); - this.outputStream.Write(spec.Count, 0, spec.Count.Length); - this.outputStream.Write(spec.Values, 0, spec.Values.Length); - } - } - - /// - /// Writes the StartOfScan marker. - /// - /// The pixel accessor providing acces to the image pixels. - private void WriteSOS(PixelAccessor pixels) - { - // 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 accessor providing acces to the image pixels. - private void Encode444(PixelAccessor pixels) - { - Block b = new Block(); - Block cb = new Block(); - Block cr = new Block(); - 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, b, cb, cr); - prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY); - prevDCCb = this.WriteBlock(cb, QuantIndex.Chrominance, prevDCCb); - prevDCCr = this.WriteBlock(cr, QuantIndex.Chrominance, prevDCCr); - } - } - } - - /// - /// Encodes the image with subsampling. The Cb and Cr components are each subsampled - /// at a factor of 2 both horizontally and vertically. - /// - /// The pixel accessor providing acces to the image pixels. - private void Encode420(PixelAccessor pixels) - { - Block b = new Block(); - Block[] cb = new Block[4]; - Block[] cr = new Block[4]; - int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - - for (int i = 0; i < 4; i++) cb[i] = new Block(); - for (int i = 0; i < 4; i++) cr[i] = new Block(); - - 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, b, cb[i], cr[i]); - prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY); - } - - this.Scale16X16_8X8(b, cb); - prevDCCb = this.WriteBlock(b, QuantIndex.Chrominance, prevDCCb); - this.Scale16X16_8X8(b, cr); - prevDCCr = this.WriteBlock(b, QuantIndex.Chrominance, prevDCCr); - } - } - } - - /// - /// 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); - } - - /// - /// Enumerates the Huffman tables - /// - private enum HuffIndex - { - LuminanceDC = 0, - - LuminanceAC = 1, - - ChrominanceDC = 2, - - ChrominanceAC = 3, - } - - /// - /// Enumerates the quantization tables - /// - private enum QuantIndex - { - /// - /// Luminance - /// - Luminance = 0, - - /// - /// Chrominance - /// - Chrominance = 1, - } - - /// - /// The Huffman encoding specifications. - /// - private struct HuffmanSpec - { - /// - /// Initializes a n ew instance of the struct. - /// - /// The number of codes. - /// The decoded values. - public HuffmanSpec(byte[] count, byte[] values) - { - this.Count = count; - this.Values = values; - } - - /// - /// Gets count[i] - The number of codes of length i bits. - /// - public readonly byte[] Count; - - /// - /// Gets value[i] - The decoded value of the i'th codeword. - /// - public readonly byte[] Values; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Jpg/JpegFormat.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegFormat.cs deleted file mode 100644 index ec9ceb6dc..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Jpg/JpegSubsample.cs b/src/ImageProcessorCore - Copy/Formats/Jpg/JpegSubsample.cs deleted file mode 100644 index 6098f6377..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Jpg/README.md b/src/ImageProcessorCore - Copy/Formats/Jpg/README.md deleted file mode 100644 index 54bc14847..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Formats/Png/GrayscaleReader.cs b/src/ImageProcessorCore - Copy/Formats/Png/GrayscaleReader.cs deleted file mode 100644 index 87f074e0b..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/GrayscaleReader.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// Color reader for reading grayscale colors from a png file. - /// - internal sealed class GrayscaleReader : IColorReader - { - /// - /// Whether t also read the alpha channel. - /// - private readonly bool useAlpha; - - /// - /// The current row. - /// - private int row; - - /// - /// Initializes a new instance of the class. - /// - /// - /// If set to true the color reader will also read the - /// alpha channel from the scanline. - /// - public GrayscaleReader(bool useAlpha) - { - this.useAlpha = useAlpha; - } - - /// - public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header) - { - int offset; - - byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); - - // We divide by 255 as we will store the colors in our floating point format. - // Stored in r-> g-> b-> a order. - if (this.useAlpha) - { - for (int x = 0; x < header.Width / 2; x++) - { - offset = ((this.row * header.Width) + x) * 4; - - // We want to convert to premultiplied alpha here. - float r = newScanline[x * 2] / 255f; - float g = newScanline[x * 2] / 255f; - float b = newScanline[x * 2] / 255f; - float a = newScanline[(x * 2) + 1] / 255f; - - Color premultiplied = Color.FromNonPremultiplied(new Color(r, g, b, a)); - - pixels[offset] = premultiplied.R; - pixels[offset + 1] = premultiplied.G; - pixels[offset + 2] = premultiplied.B; - pixels[offset + 3] = premultiplied.A; - } - } - else - { - for (int x = 0; x < header.Width; x++) - { - offset = ((this.row * header.Width) + x) * 4; - - pixels[offset] = newScanline[x] / 255f; - pixels[offset + 1] = newScanline[x] / 255f; - pixels[offset + 2] = newScanline[x] / 255f; - pixels[offset + 3] = 1; - } - } - - this.row++; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/IColorReader.cs b/src/ImageProcessorCore - Copy/Formats/Png/IColorReader.cs deleted file mode 100644 index 68183fac7..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/IColorReader.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// Encapsulates methods for color readers, which are responsible for reading - /// different color formats from a png file. - /// - public interface IColorReader - { - /// - /// Reads the specified scanline. - /// - /// The scanline. - /// The pixels, where the colors should be stored in RGBA format. - /// - /// The header, which contains information about the png file, like - /// the width of the image and the height. - /// - void ReadScanline(byte[] scanline, float[] pixels, PngHeader header); - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PaletteIndexReader.cs b/src/ImageProcessorCore - Copy/Formats/Png/PaletteIndexReader.cs deleted file mode 100644 index 40de59dbb..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PaletteIndexReader.cs +++ /dev/null @@ -1,99 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// A color reader for reading palette indices from the png file. - /// - internal sealed class PaletteIndexReader : IColorReader - { - /// - /// The palette. - /// - private readonly byte[] palette; - - /// - /// The alpha palette. - /// - private readonly byte[] paletteAlpha; - - /// - /// The current row. - /// - private int row; - - /// - /// Initializes a new instance of the class. - /// - /// The palette as simple byte array. It will contains 3 values for each - /// color, which represents the red-, the green- and the blue channel. - /// The alpha palette. Can be null, if the image does not have an - /// alpha channel and can contain less entries than the number of colors in the palette. - public PaletteIndexReader(byte[] palette, byte[] paletteAlpha) - { - this.palette = palette; - this.paletteAlpha = paletteAlpha; - } - - /// - public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header) - { - byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); - int offset, index; - - if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) - { - // If the alpha palette is not null and does one or - // more entries, this means, that the image contains and alpha - // channel and we should try to read it. - for (int i = 0; i < header.Width; i++) - { - index = newScanline[i]; - - offset = ((this.row * header.Width) + i) * 4; - int pixelOffset = index * 3; - - // BUGFIX changed newScanline[] to this.palette[] , 99% sure it was a typo and not intent - float r = this.palette[pixelOffset] / 255f; - float g = this.palette[pixelOffset + 1] / 255f; - float b = this.palette[pixelOffset + 2] / 255f; - float a = this.paletteAlpha.Length > index - ? this.paletteAlpha[index] / 255f - : 1; - - Color color = new Color(r, g, b, a); - if (color.A < 1) - { - // We want to convert to premultiplied alpha here. - color = Color.FromNonPremultiplied(color); - } - - pixels[offset] = color.R; - pixels[offset + 1] = color.G; - pixels[offset + 2] = color.B; - pixels[offset + 3] = color.A; - } - } - else - { - for (int i = 0; i < header.Width; i++) - { - index = newScanline[i]; - - offset = ((this.row * header.Width) + i) * 4; - int pixelOffset = index * 3; - - pixels[offset] = this.palette[pixelOffset] / 255f; - pixels[offset + 1] = this.palette[pixelOffset + 1] / 255f; - pixels[offset + 2] = this.palette[pixelOffset + 2] / 255f; - pixels[offset + 3] = 1; - } - } - - this.row++; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngChunk.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngChunk.cs deleted file mode 100644 index 31ea703a6..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/PngChunkTypes.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngChunkTypes.cs deleted file mode 100644 index 5c35b3d4d..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/PngColorTypeInformation.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngColorTypeInformation.cs deleted file mode 100644 index 9909cf47c..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PngColorTypeInformation.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - - /// - /// Contains information that are required when loading a png with a specific color type. - /// - internal sealed class PngColorTypeInformation - { - /// - /// Initializes a new instance of the class with - /// the scanline factory, the function to create the color reader and the supported bit depths. - /// - /// The scanline factor. - /// The supported bit depths. - /// The factory to create the color reader. - public PngColorTypeInformation(int scanlineFactor, int[] supportedBitDepths, Func scanlineReaderFactory) - { - this.ChannelsPerColor = scanlineFactor; - this.ScanlineReaderFactory = scanlineReaderFactory; - this.SupportedBitDepths = supportedBitDepths; - } - - /// - /// Gets an array with the bit depths that are supported for the color type - /// where this object is created for. - /// - /// The supported bit depths that can be used in combination with this color type. - public int[] SupportedBitDepths { get; private set; } - - /// - /// Gets a function that is used the create the color reader for the color type where - /// this object is created for. - /// - /// The factory function to create the color type. - public Func ScanlineReaderFactory { get; private set; } - - /// - /// Gets a factor that is used when iterating through the scan lines. - /// - /// The scanline factor. - public int ChannelsPerColor { get; private set; } - - /// - /// Creates the color reader for the color type where this object is create for. - /// - /// The palette of the image. Can be null when no palette is used. - /// The alpha palette of the image. Can be null when - /// no palette is used for the image or when the image has no alpha. - /// The color reader for the image. - public IColorReader CreateColorReader(byte[] palette, byte[] paletteAlpha) - { - return this.ScanlineReaderFactory(palette, paletteAlpha); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngDecoder.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngDecoder.cs deleted file mode 100644 index 7e92f2614..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PngDecoder.cs +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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). - /// Greyscale with alpha (8 bit). - /// Greyscale 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 to decode to. - /// The containing image data. - public void Decode(Image image, Stream stream) - { - new PngDecoderCore().Decode(image, stream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngDecoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngDecoderCore.cs deleted file mode 100644 index a8e3596b0..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PngDecoderCore.cs +++ /dev/null @@ -1,527 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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(); - - /// - /// The image to decode. - /// - private Image currentImage; - - /// - /// The stream to decode from. - /// - private Stream currentStream; - - /// - /// The png header. - /// - private PngHeader header; - - /// - /// Initializes static members of the class. - /// - static PngDecoderCore() - { - ColorTypes.Add( - 0, - new PngColorTypeInformation(1, new[] { 1, 2, 4, 8 }, (p, a) => new GrayscaleReader(false))); - - ColorTypes.Add( - 2, - new PngColorTypeInformation(3, new[] { 8 }, (p, a) => new TrueColorReader(false))); - - ColorTypes.Add( - 3, - new PngColorTypeInformation(1, new[] { 1, 2, 4, 8 }, (p, a) => new PaletteIndexReader(p, a))); - - ColorTypes.Add( - 4, - new PngColorTypeInformation(2, new[] { 8 }, (p, a) => new GrayscaleReader(true))); - - ColorTypes.Add(6, - new PngColorTypeInformation(4, new[] { 8 }, (p, a) => new TrueColorReader(true))); - } - - /// - /// Decodes the stream to the image. - /// - /// 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) - { - this.currentImage = image; - this.currentStream = stream; - this.currentStream.Seek(8, SeekOrigin.Current); - - bool isEndChunkReached = false; - - byte[] palette = null; - byte[] paletteAlpha = null; - - using (MemoryStream dataStream = new MemoryStream()) - { - PngChunk currentChunk; - while ((currentChunk = this.ReadChunk()) != null) - { - if (isEndChunkReached) - { - throw new ImageFormatException("Image does not end with end chunk."); - } - - if (currentChunk.Type == PngChunkTypes.Header) - { - this.ReadHeaderChunk(currentChunk.Data); - this.ValidateHeader(); - } - else if (currentChunk.Type == PngChunkTypes.Physical) - { - this.ReadPhysicalChunk(currentChunk.Data); - } - else if (currentChunk.Type == PngChunkTypes.Data) - { - dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length); - } - else if (currentChunk.Type == PngChunkTypes.Palette) - { - palette = currentChunk.Data; - } - else if (currentChunk.Type == PngChunkTypes.PaletteAlpha) - { - paletteAlpha = currentChunk.Data; - } - else if (currentChunk.Type == PngChunkTypes.Text) - { - this.ReadTextChunk(currentChunk.Data); - } - else if (currentChunk.Type == PngChunkTypes.End) - { - isEndChunkReached = true; - } - } - - if (this.header.Width > ImageBase.MaxWidth || this.header.Height > ImageBase.MaxHeight) - { - throw new ArgumentOutOfRangeException( - $"The input png '{this.header.Width}x{this.header.Height}' is bigger than the " - + $"max allowed size '{ImageBase.MaxWidth}x{ImageBase.MaxHeight}'"); - } - - float[] pixels = new float[this.header.Width * this.header.Height * 4]; - - PngColorTypeInformation colorTypeInformation = ColorTypes[this.header.ColorType]; - - if (colorTypeInformation != null) - { - IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha); - - this.ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation); - } - - image.SetPixels(this.header.Width, this.header.Height, pixels); - } - } - - /// - /// 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 neighbour pixel. - /// The above neighbour pixel. - /// The upper left neighbour pixel. - /// - /// The . - /// - private static byte PaethPredicator(byte left, byte above, byte upperLeft) - { - byte predicator; - - 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) - { - predicator = left; - } - else if (pb <= pc) - { - predicator = above; - } - else - { - predicator = upperLeft; - } - - return predicator; - } - - /// - /// Reads the data chunk containing physical dimension data. - /// - /// The data containing physical data. - private void ReadPhysicalChunk(byte[] data) - { - Array.Reverse(data, 0, 4); - Array.Reverse(data, 4, 4); - - // 39.3700787 = inches in a meter. - this.currentImage.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d; - this.currentImage.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d; - } - - /// - /// Calculates the scanline length. - /// - /// The color type information. - /// The representing the length. - private int CalculateScanlineLength(PngColorTypeInformation colorTypeInformation) - { - int scanlineLength = this.header.Width * this.header.BitDepth * colorTypeInformation.ChannelsPerColor; - - int amount = scanlineLength % 8; - if (amount != 0) - { - scanlineLength += 8 - amount; - } - - return scanlineLength / 8; - } - - /// - /// Calculates a scanline step. - /// - /// The color type information. - /// The representing the length of each step. - private int CalculateScanlineStep(PngColorTypeInformation colorTypeInformation) - { - int scanlineStep = 1; - - if (this.header.BitDepth >= 8) - { - scanlineStep = (colorTypeInformation.ChannelsPerColor * this.header.BitDepth) / 8; - } - - return scanlineStep; - } - - /// - /// Reads the scanlines within the image. - /// - /// The containing data. - /// - /// The containing pixel data. - /// The color reader. - /// The color type information. - private void ReadScanlines(MemoryStream dataStream, float[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation) - { - dataStream.Position = 0; - - int scanlineLength = this.CalculateScanlineLength(colorTypeInformation); - int scanlineStep = this.CalculateScanlineStep(colorTypeInformation); - - byte[] lastScanline = new byte[scanlineLength]; - byte[] currentScanline = new byte[scanlineLength]; - int filter = 0, column = -1; - - using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream)) - { - int readByte; - while ((readByte = compressedStream.ReadByte()) >= 0) - { - if (column == -1) - { - filter = readByte; - - column++; - } - else - { - currentScanline[column] = (byte)readByte; - - byte a; - byte b; - byte c; - - if (column >= scanlineStep) - { - a = currentScanline[column - scanlineStep]; - c = lastScanline[column - scanlineStep]; - } - else - { - a = 0; - c = 0; - } - - b = lastScanline[column]; - - if (filter == 1) - { - currentScanline[column] = (byte)(currentScanline[column] + a); - } - else if (filter == 2) - { - currentScanline[column] = (byte)(currentScanline[column] + b); - } - else if (filter == 3) - { - currentScanline[column] = (byte)(currentScanline[column] + (byte)((a + b) / 2)); - } - else if (filter == 4) - { - currentScanline[column] = (byte)(currentScanline[column] + PaethPredicator(a, b, c)); - } - - column++; - - if (column == scanlineLength) - { - colorReader.ReadScanline(currentScanline, pixels, this.header); - column = -1; - - this.Swap(ref currentScanline, ref lastScanline); - } - } - } - } - } - - /// - /// Reads a text chunk containing image properties from the data. - /// - /// The containing data. - private void ReadTextChunk(byte[] data) - { - 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); - - this.currentImage.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(); - - Array.Reverse(data, 0, 4); - Array.Reverse(data, 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.FilterMethod = data[11]; - this.header.InterlaceMethod = data[12]; - this.header.CompressionMethod = data[10]; - } - - /// - /// Validates the png header. - /// - /// - /// Thrown if the image does pass validation. - /// - private void ValidateHeader() - { - if (!ColorTypes.ContainsKey(this.header.ColorType)) - { - throw new ImageFormatException("Color type is not supported or not valid."); - } - - if (!ColorTypes[this.header.ColorType].SupportedBitDepths.Contains(this.header.BitDepth)) - { - throw new ImageFormatException("Bit depth is not supported or not valid."); - } - - if (this.header.FilterMethod != 0) - { - throw new ImageFormatException("The png specification only defines 0 as filter method."); - } - - if (this.header.InterlaceMethod != 0) - { - throw new ImageFormatException("Interlacing is not supported."); - } - } - - /// - /// Reads a chunk from the stream. - /// - /// - /// The . - /// - private PngChunk ReadChunk() - { - PngChunk chunk = new PngChunk(); - - if (this.ReadChunkLength(chunk) == 0) - { - return null; - } - - byte[] typeBuffer = this.ReadChunkType(chunk); - - this.ReadChunkData(chunk); - this.ReadChunkCrc(chunk, typeBuffer); - - return chunk; - } - - /// - /// Reads the cycle redundancy chunk from the data. - /// - /// The chunk. - /// The type buffer. - /// - /// Thrown if the input stream is not valid or corrupt. - /// - private void ReadChunkCrc(PngChunk chunk, byte[] typeBuffer) - { - byte[] crcBuffer = new byte[4]; - - int numBytes = this.currentStream.Read(crcBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - Array.Reverse(crcBuffer); - - chunk.Crc = BitConverter.ToUInt32(crcBuffer, 0); - - Crc32 crc = new Crc32(); - crc.Update(typeBuffer); - 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. - /// - /// The containing identifying information. - /// - /// - /// Thrown if the input stream is not valid. - /// - private byte[] ReadChunkType(PngChunk chunk) - { - byte[] typeBuffer = new byte[4]; - - int numBytes = this.currentStream.Read(typeBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - char[] chars = new char[4]; - chars[0] = (char)typeBuffer[0]; - chars[1] = (char)typeBuffer[1]; - chars[2] = (char)typeBuffer[2]; - chars[3] = (char)typeBuffer[3]; - - chunk.Type = new string(chars); - - return typeBuffer; - } - - /// - /// 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) - { - byte[] lengthBuffer = new byte[4]; - - int numBytes = this.currentStream.Read(lengthBuffer, 0, 4); - if (numBytes >= 1 && numBytes <= 3) - { - throw new ImageFormatException("Image stream is not valid!"); - } - - Array.Reverse(lengthBuffer); - - chunk.Length = BitConverter.ToInt32(lengthBuffer, 0); - - return numBytes; - } - - /// - /// Swaps two references. - /// - /// The type of the references to swap. - /// The first reference. - /// The second reference. - private void Swap(ref TRef lhs, ref TRef rhs) - where TRef : class - { - TRef tmp = lhs; - - lhs = rhs; - rhs = tmp; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngEncoder.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngEncoder.cs deleted file mode 100644 index 18deb1046..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PngEncoder.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - - using ImageProcessorCore.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; } - - /// - public string MimeType => "image/png"; - - /// - public string Extension => "png"; - - /// - /// 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; - - /// - /// The quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } = 128; - - /// - /// 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(ImageBase image, Stream stream) - { - PngEncoderCore encoder = new PngEncoderCore - { - CompressionLevel = this.CompressionLevel, - Gamma = this.Gamma, - Quality = this.Quality, - Quantizer = this.Quantizer, - WriteGamma = this.WriteGamma, - Threshold = this.Threshold - }; - - encoder.Encode(image, stream); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngEncoderCore.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngEncoderCore.cs deleted file mode 100644 index 7e61f736e..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/PngEncoderCore.cs +++ /dev/null @@ -1,470 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - using System; - using System.IO; - using System.Threading.Tasks; - - using ImageProcessorCore.Quantizers; - - /// - /// Performs the png encoding operation. - /// TODO: Perf. There's lots of array parsing 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; - - /// - /// The number of bits required to encode the colors in the png. - /// - private byte bitDepth; - - /// - /// The quantized image result. - /// - private QuantizedImage quantized; - - /// - /// Gets or sets the quality of output for images. - /// - public int Quality { get; set; } - - /// - /// 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; - - /// - /// The quantizer for reducing the color count. - /// - public IQuantizer Quantizer { get; set; } - - /// - /// Gets or sets the transparency threshold. - /// - public byte Threshold { get; set; } = 128; - - /// - public void Encode(ImageBase image, Stream stream) - { - Guard.NotNull(image, nameof(image)); - Guard.NotNull(stream, nameof(stream)); - - // Write the png header. - stream.Write( - new byte[] - { - 0x89, // Set the high bit. - 0x50, // P - 0x4E, // N - 0x47, // G - 0x0D, // Line ending CRLF - 0x0A, // Line ending CRLF - 0x1A, // EOF - 0x0A // LF - }, - 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; - - 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; - } - - // TODO: Add more color options here. - PngHeader header = new PngHeader - { - Width = image.Width, - Height = image.Height, - ColorType = (byte)(this.Quality <= 256 ? 3 : 6), // 3 = indexed, 6= Each pixel is an R,G,B triple, followed by an alpha sample. - BitDepth = this.bitDepth, - FilterMethod = 0, // None - CompressionMethod = 0, - InterlaceMethod = 0 - }; - - this.WriteHeaderChunk(stream, header); - this.WritePaletteChunk(stream, header, image); - this.WritePhysicalChunk(stream, image); - this.WriteGammaChunk(stream); - - using (PixelAccessor pixels = image.Lock()) - { - this.WriteDataChunks(stream, pixels); - } - - 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); - - Array.Reverse(buffer); - Array.Copy(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); - - Array.Reverse(buffer); - - 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); - - Array.Reverse(buffer); - - stream.Write(buffer, 0, 4); - } - - /// - /// Writes the header chunk to the stream. - /// - /// The containing image data. - /// The . - private void WriteHeaderChunk(Stream stream, PngHeader header) - { - byte[] chunkData = new byte[13]; - - WriteInteger(chunkData, 0, header.Width); - WriteInteger(chunkData, 4, header.Height); - - chunkData[8] = header.BitDepth; - chunkData[9] = header.ColorType; - chunkData[10] = header.CompressionMethod; - chunkData[11] = header.FilterMethod; - chunkData[12] = header.InterlaceMethod; - - this.WriteChunk(stream, PngChunkTypes.Header, chunkData); - } - - /// - /// Writes the palette chunk to the stream. - /// - /// The containing image data. - /// The . - /// The image to encode. - private void WritePaletteChunk(Stream stream, PngHeader header, ImageBase image) - { - if (this.Quality > 256) - { - return; - } - - if (this.Quantizer == null) - { - this.Quantizer = new WuQuantizer { Threshold = this.Threshold }; - } - - // Quantize the image returning a palette. - this.quantized = this.Quantizer.Quantize(image, this.Quality); - - // Grab the palette and write it to the stream. - Bgra32[] palette = this.quantized.Palette; - int pixelCount = palette.Length; - - // Get max colors for bit depth. - int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3; - byte[] colorTable = new byte[colorTableLength]; - - Parallel.For(0, pixelCount, - i => - { - int offset = i * 3; - Bgra32 color = palette[i]; - - colorTable[offset] = color.R; - colorTable[offset + 1] = color.G; - colorTable[offset + 2] = color.B; - }); - - this.WriteChunk(stream, PngChunkTypes.Palette, colorTable); - - // Write the transparency data - if (this.quantized.TransparentIndex > -1) - { - this.WriteChunk(stream, PngChunkTypes.PaletteAlpha, new[] { (byte)this.quantized.TransparentIndex }); - } - } - - /// - /// Writes the physical dimension information to the stream. - /// - /// The containing image data. - /// The image base. - private void WritePhysicalChunk(Stream stream, ImageBase imageBase) - { - 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); - - byte[] chunkData = new byte[9]; - - WriteInteger(chunkData, 0, dpmX); - WriteInteger(chunkData, 4, dpmY); - - chunkData[8] = 1; - - this.WriteChunk(stream, PngChunkTypes.Physical, chunkData); - } - } - - /// - /// 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[] fourByteData = new byte[4]; - - byte[] size = BitConverter.GetBytes(gammaValue); - - fourByteData[0] = size[3]; - fourByteData[1] = size[2]; - fourByteData[2] = size[1]; - fourByteData[3] = size[0]; - - this.WriteChunk(stream, PngChunkTypes.Gamma, fourByteData); - } - } - - /// - /// Writes the pixel information to the stream. - /// - /// The containing image data. - /// The image pixels. - private void WriteDataChunks(Stream stream, PixelAccessor pixels) - { - byte[] data; - int imageWidth = pixels.Width; - int imageHeight = pixels.Height; - - // Indexed image. - if (this.Quality <= 256) - { - int rowLength = imageWidth + 1; - data = new byte[rowLength * imageHeight]; - - Parallel.For(0, imageHeight, y => - { - int dataOffset = (y * rowLength); - byte compression = 0; - if (y > 0) - { - compression = 2; - } - data[dataOffset++] = compression; - for (int x = 0; x < imageWidth; x++) - { - data[dataOffset++] = this.quantized.Pixels[(y * imageWidth) + x]; - if (y > 0) - { - data[dataOffset - 1] -= this.quantized.Pixels[((y - 1) * imageWidth) + x]; - } - } - }); - } - else - { - // TrueColor image. - data = new byte[(imageWidth * imageHeight * 4) + pixels.Height]; - - int rowLength = (imageWidth * 4) + 1; - - Parallel.For(0, imageHeight, y => - { - byte compression = 0; - if (y > 0) - { - compression = 2; - } - - data[y * rowLength] = compression; - - for (int x = 0; x < imageWidth; x++) - { - Bgra32 color = Color.ToNonPremultiplied(pixels[x, y]); - - // Calculate the offset for the new array. - int dataOffset = (y * rowLength) + (x * 4) + 1; - data[dataOffset] = color.R; - data[dataOffset + 1] = color.G; - data[dataOffset + 2] = color.B; - data[dataOffset + 3] = color.A; - - if (y > 0) - { - color = Color.ToNonPremultiplied(pixels[x, y - 1]); - - data[dataOffset] -= color.R; - data[dataOffset + 1] -= color.G; - data[dataOffset + 2] -= color.B; - data[dataOffset + 3] -= color.A; - } - } - }); - } - - byte[] buffer; - int bufferLength; - - MemoryStream memoryStream = null; - try - { - memoryStream = new MemoryStream(); - - using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel)) - { - deflateStream.Write(data, 0, data.Length); - } - - bufferLength = (int)memoryStream.Length; - buffer = memoryStream.ToArray(); - } - finally - { - memoryStream?.Dispose(); - } - - 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) - { - WriteInteger(stream, length); - - byte[] typeArray = new byte[4]; - typeArray[0] = (byte)type[0]; - typeArray[1] = (byte)type[1]; - typeArray[2] = (byte)type[2]; - typeArray[3] = (byte)type[3]; - - stream.Write(typeArray, 0, 4); - - if (data != null) - { - stream.Write(data, offset, length); - } - - Crc32 crc32 = new Crc32(); - crc32.Update(typeArray); - - if (data != null) - { - crc32.Update(data, offset, length); - } - - WriteInteger(stream, (uint)crc32.Value); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/PngFormat.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngFormat.cs deleted file mode 100644 index 38a0a7c38..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/PngHeader.cs b/src/ImageProcessorCore - Copy/Formats/Png/PngHeader.cs deleted file mode 100644 index dfa30794a..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/README.md b/src/ImageProcessorCore - Copy/Formats/Png/README.md deleted file mode 100644 index 8ade37956..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Formats/Png/TrueColorReader.cs b/src/ImageProcessorCore - Copy/Formats/Png/TrueColorReader.cs deleted file mode 100644 index 47c39b029..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/TrueColorReader.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Formats -{ - /// - /// Color reader for reading true colors from a png file. Only colors - /// with 24 or 32 bit (3 or 4 bytes) per pixel are supported at the moment. - /// - internal sealed class TrueColorReader : IColorReader - { - /// - /// Whether t also read the alpha channel. - /// - private readonly bool useAlpha; - - /// - /// The current row. - /// - private int row; - - /// - /// Initializes a new instance of the class. - /// - /// if set to true the color reader will also read the - /// alpha channel from the scanline. - public TrueColorReader(bool useAlpha) - { - this.useAlpha = useAlpha; - } - - /// - public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header) - { - int offset; - - byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); - - if (this.useAlpha) - { - for (int x = 0; x < newScanline.Length; x += 4) - { - offset = ((this.row * header.Width) + (x >> 2)) * 4; - - // We want to convert to premultiplied alpha here. - float r = newScanline[x] / 255f; - float g = newScanline[x + 1] / 255f; - float b = newScanline[x + 2] / 255f; - float a = newScanline[x + 3] / 255f; - - Color premultiplied = Color.FromNonPremultiplied(new Color(r, g, b, a)); - - pixels[offset] = premultiplied.R; - pixels[offset + 1] = premultiplied.G; - pixels[offset + 2] = premultiplied.B; - pixels[offset + 3] = premultiplied.A; - } - } - else - { - for (int x = 0; x < newScanline.Length / 3; x++) - { - offset = ((this.row * header.Width) + x) * 4; - int pixelOffset = x * 3; - - pixels[offset] = newScanline[pixelOffset] / 255f; - pixels[offset + 1] = newScanline[pixelOffset + 1] / 255f; - pixels[offset + 2] = newScanline[pixelOffset + 2] / 255f; - pixels[offset + 3] = 1; - } - } - - this.row++; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Formats/Png/Zlib/Adler32.cs b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/Adler32.cs deleted file mode 100644 index f58ec34c2..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/Zlib/Crc32.cs b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/Crc32.cs deleted file mode 100644 index da42e8dae..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/Zlib/IChecksum.cs b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/IChecksum.cs deleted file mode 100644 index 077a5ad2a..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Formats/Png/Zlib/README.md b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/README.md deleted file mode 100644 index c297a91d5..000000000 --- a/src/ImageProcessorCore - Copy/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/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibDeflateStream.cs deleted file mode 100644 index a2c0ca202..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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 decompressing the input stream. - private DeflateStream deflateStream; - - /// - /// Initializes a new instance of - /// - /// 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/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibInflateStream.cs deleted file mode 100644 index 4373b5fd1..000000000 --- a/src/ImageProcessorCore - Copy/Formats/Png/Zlib/ZlibInflateStream.cs +++ /dev/null @@ -1,205 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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 - { - /// - /// 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 raw stream containing the uncompressed image data. - /// - private readonly Stream rawStream; - - /// - /// The read crc data. - /// - private byte[] crcread; - - // The stream responsible for decompressing the input stream. - private DeflateStream deflateStream; - - 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/ImageProcessorCore - Copy/IImageBase.cs b/src/ImageProcessorCore - Copy/IImageBase.cs deleted file mode 100644 index a72103377..000000000 --- a/src/ImageProcessorCore - Copy/IImageBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace ImageProcessorCore -{ - public interface IImageBase - where TPackedVector : IPackedVector - { - Rectangle Bounds { get; } - int FrameDelay { get; set; } - int Height { get; } - double PixelRatio { get; } - TPackedVector[] Pixels { get; } - int Quality { 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; } - - int Width { get; } - - void ClonePixels(int width, int height, TPackedVector[] pixels); - IPixelAccessor Lock(); - void SetPixels(int width, int height, TPackedVector[] pixels); - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/IImageFrame.cs b/src/ImageProcessorCore - Copy/IImageFrame.cs deleted file mode 100644 index 1565879a7..000000000 --- a/src/ImageProcessorCore - Copy/IImageFrame.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ImageProcessorCore -{ - public interface IImageFrame : IImageBase - where TPacked : IPackedVector - { - } -} diff --git a/src/ImageProcessorCore - Copy/IImageProcessor.cs b/src/ImageProcessorCore - Copy/IImageProcessor.cs deleted file mode 100644 index ad6e4ac76..000000000 --- a/src/ImageProcessorCore - Copy/IImageProcessor.cs +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// A delegate which is called as progress is made processing an image. - /// - /// The source of the event. - /// An object that contains the event data. - public delegate void ProgressEventHandler(object sender, ProgressEventArgs e); - - /// - /// Encapsulates methods to alter the pixels of an image. - /// - public interface IImageProcessor - { - /// - /// Event fires when each row of the source image has been processed. - /// - /// - /// This event may be called from threads other than the client thread, and from multiple threads simultaneously. - /// Individual row notifications may arrived out of order. - /// - event ProgressEventHandler OnProgress; - - /// - /// Applies the process to the specified portion of the specified . - /// - /// The type of pixels contained within the image. - /// 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) where TPackedVector : IPackedVector; - - /// - /// Applies the process to the specified portion of the specified at the specified - /// location and with the specified size. - /// - /// The type of pixels contained within the image. - /// 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) where TPackedVector : IPackedVector; - } -} diff --git a/src/ImageProcessorCore - Copy/IO/BigEndianBitConverter.cs b/src/ImageProcessorCore - Copy/IO/BigEndianBitConverter.cs deleted file mode 100644 index 6c624c6a6..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/IO/EndianBinaryReader.cs b/src/ImageProcessorCore - Copy/IO/EndianBinaryReader.cs deleted file mode 100644 index e2fc14a05..000000000 --- a/src/ImageProcessorCore - Copy/IO/EndianBinaryReader.cs +++ /dev/null @@ -1,616 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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/ImageProcessorCore - Copy/IO/EndianBinaryWriter.cs b/src/ImageProcessorCore - Copy/IO/EndianBinaryWriter.cs deleted file mode 100644 index 0f37b9a13..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/IO/EndianBitConverter.cs b/src/ImageProcessorCore - Copy/IO/EndianBitConverter.cs deleted file mode 100644 index d95527002..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/IO/Endianness.cs b/src/ImageProcessorCore - Copy/IO/Endianness.cs deleted file mode 100644 index e8e4ef4c2..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/IO/LittleEndianBitConverter.cs b/src/ImageProcessorCore - Copy/IO/LittleEndianBitConverter.cs deleted file mode 100644 index 70e65d909..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Image.cs b/src/ImageProcessorCore - Copy/Image.cs deleted file mode 100644 index c8dc861d6..000000000 --- a/src/ImageProcessorCore - Copy/Image.cs +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System.IO; - using System.Text; - - using System; - using System.Collections.Generic; - using System.Linq; - - using Formats; - - /// - /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. - /// - /// - /// The packed vector containing pixel information. - /// - public class Image : ImageBase - where TPackedVector : IPackedVector - { - /// - /// 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) - { - foreach (ImageFrame frame in other.Frames) - { - if (frame != null) - { - this.Frames.Add(new ImageFrame(frame)); - } - } - - this.RepeatCount = other.RepeatCount; - this.HorizontalResolution = other.HorizontalResolution; - this.VerticalResolution = other.VerticalResolution; - this.CurrentImageFormat = other.CurrentImageFormat; - } - - /// - /// 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; } - - /// - public override IPixelAccessor Lock() - { - return Bootstrapper.Instance.GetPixelAccessor(this); - } - - /// - /// 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 void Save(Stream stream) - { - Guard.NotNull(stream, nameof(stream)); - this.CurrentImageFormat.Encoder.Encode(this, stream); - } - - /// - /// 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 void Save(Stream stream, IImageFormat format) - { - Guard.NotNull(stream, nameof(stream)); - format.Encoder.Encode(this, stream); - } - - /// - /// 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. - public void Save(Stream stream, IImageEncoder encoder) - { - Guard.NotNull(stream, nameof(stream)); - encoder.Encode(this, stream); - } - - /// - /// Returns a Base64 encoded string from the given image. - /// - /// data:image/gif;base64,R0lGODlhAQABAIABAEdJRgAAACwAAAAAAQABAAACAkQBAA== - /// The - public override string ToString() - { - using (MemoryStream stream = new MemoryStream()) - { - this.Save(stream); - stream.Flush(); - return $"data:{this.CurrentImageFormat.Encoder.MimeType};base64,{Convert.ToBase64String(stream.ToArray())}"; - } - } - - /// - /// 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) - { - throw new NotSupportedException("The stream does not support seeking."); - } - - 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; - } - } - - 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()); - } - } -} diff --git a/src/ImageProcessorCore - Copy/ImageBase.cs b/src/ImageProcessorCore - Copy/ImageBase.cs deleted file mode 100644 index 5fa83df4c..000000000 --- a/src/ImageProcessorCore - Copy/ImageBase.cs +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - - /// - /// The base class of all images. Encapsulates the basic properties and methods required to manipulate images - /// in different pixel formats. - /// - /// - /// The packed vector pixels format. - /// - public abstract class ImageBase : IImageBase - where TPacked : IPackedVector - { - /// - /// 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) - { - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - - this.Width = width; - this.Height = height; - this.Pixels = new TPacked[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.Quality = other.Quality; - this.FrameDelay = other.FrameDelay; - - // Copy the pixels. - this.Pixels = new TPacked[this.Width * this.Height]; - Array.Copy(other.Pixels, this.Pixels, other.Pixels.Length); - } - - /// - /// Gets or sets the maximum allowable width in pixels. - /// - public int MaxWidth { get; set; } = int.MaxValue; - - /// - /// Gets or sets the maximum allowable height in pixels. - /// - public int MaxHeight { get; set; } = int.MaxValue; - - /// - /// Gets the pixels as an array of the given packed pixel format. - /// - public TPacked[] Pixels { get; private set; } - - /// - /// Gets the width in pixels. - /// - public int Width { get; private set; } - - /// - /// Gets the height in pixels. - /// - public int Height { get; private set; } - - /// - /// Gets the pixel ratio made up of the width and height. - /// - public double PixelRatio => (double)this.Width / this.Height; - - /// - /// Gets the representing the bounds of the image. - /// - public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height); - - /// - /// Gets or sets th quality of the image. This affects the output quality of lossy image formats. - /// - public 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. - /// - public int FrameDelay { get; set; } - - /// - /// 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 colors. 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. - /// - public void SetPixels(int width, int height, TPacked[] pixels) - { - if (width <= 0) - { - throw new ArgumentOutOfRangeException(nameof(width), "Width must be greater than or equals than zero."); - } - - if (height <= 0) - { - throw new ArgumentOutOfRangeException(nameof(height), "Height must be greater than or equal than zero."); - } - - if (pixels.Length != width * height) - { - throw new ArgumentException("Pixel array must have the length of Width * Height."); - } - - this.Width = width; - this.Height = height; - this.Pixels = 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 colors. 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. - /// - public void ClonePixels(int width, int height, TPacked[] pixels) - { - if (width <= 0) - { - throw new ArgumentOutOfRangeException(nameof(width), "Width must be greater than or equals than zero."); - } - - if (height <= 0) - { - throw new ArgumentOutOfRangeException(nameof(height), "Height must be greater than or equal than zero."); - } - - 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. - this.Pixels = new TPacked[pixels.Length]; - Array.Copy(pixels, this.Pixels, pixels.Length); - } - - /// - /// Locks the image providing access to the pixels. - /// - /// It is imperative that the accessor is correctly disposed off after use. - /// - /// - /// The - public abstract IPixelAccessor Lock(); - } -} diff --git a/src/ImageProcessorCore - Copy/ImageExtensions.cs b/src/ImageProcessorCore - Copy/ImageExtensions.cs deleted file mode 100644 index ea320aad4..000000000 --- a/src/ImageProcessorCore - Copy/ImageExtensions.cs +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.IO; - - using Formats; - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Saves the image to the given stream with the bmp format. - /// - /// The image this method extends. - /// The stream to save the image to. - /// Thrown if the stream is null. - public static void SaveAsBmp(this ImageBase source, Stream stream) => new BmpEncoder().Encode(source, stream); - - /// - /// Saves the image to the given stream with the png format. - /// - /// 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. - public static void SaveAsPng(this ImageBase source, Stream stream, int quality = Int32.MaxValue) => new PngEncoder { Quality = quality }.Encode(source, stream); - - /// - /// Saves the image to the given stream with the jpeg format. - /// - /// 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. - public static void SaveAsJpeg(this ImageBase source, Stream stream, int quality = 75) => new JpegEncoder { Quality = quality }.Encode(source, stream); - - /// - /// Saves the image to the given stream with the gif format. - /// - /// 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. - public static void SaveAsGif(this ImageBase source, Stream stream, int quality = 256) => new GifEncoder { Quality = quality }.Encode(source, stream); - - /// - /// Applies the collection of processors to the image. - /// This method does not resize the target image. - /// - /// The image this method extends. - /// The processor to apply to the image. - /// The . - public static Image Process(this Image source, IImageProcessor processor) - { - return Process(source, source.Bounds, processor); - } - - /// - /// Applies the collection of processors to the image. - /// This method does not resize the target image. - /// - /// 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 . - public static Image Process(this Image source, Rectangle sourceRectangle, IImageProcessor processor) - { - return PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle)); - } - - /// - /// Applies the collection of processors to the image. - /// - /// This method is not chainable. - /// - /// - /// The source image. Cannot be null. - /// The target image width. - /// The target image height. - /// The processor to apply to the image. - /// The . - public static Image Process(this Image source, int width, int height, IImageSampler sampler) - { - return Process(source, width, height, source.Bounds, default(Rectangle), sampler); - } - - /// - /// Applies the collection of processors to the image. - /// - /// This method does will resize the target image if the source and target rectangles are different. - /// - /// - /// 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 . - public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler) - { - return PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); - } - - /// - /// Performs the given action on the source image. - /// - /// The image to perform the action against. - /// Whether to clone the image. - /// The to perform against the image. - /// The . - /// Thrown if the has been disposed. - private static Image PerformAction(Image source, bool clone, Action action) - { - Image transformedImage = clone - ? new Image(source) - : new Image - { - // Several properties require copying - // TODO: Check why we need to set these? - Quality = source.Quality, - HorizontalResolution = source.HorizontalResolution, - VerticalResolution = source.VerticalResolution, - CurrentImageFormat = source.CurrentImageFormat, - RepeatCount = source.RepeatCount - }; - - 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/ImageProcessorCore - Copy/ImageFrame.cs b/src/ImageProcessorCore - Copy/ImageFrame.cs deleted file mode 100644 index 479d9dd9b..000000000 --- a/src/ImageProcessorCore - Copy/ImageFrame.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - /// - /// Represents a single frame in a animation. - /// - /// - /// The packed vector containing pixel information. - /// - public class ImageFrame : ImageBase - where TPackedVector : IPackedVector - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The frame to create the frame from. - /// - public ImageFrame(ImageFrame frame) - : base(frame) - { - } - - /// - public override IPixelAccessor Lock() - { - return Bootstrapper.Instance.GetPixelAccessor(this); - } - } -} diff --git a/src/ImageProcessorCore - Copy/ImageProcessor.cs b/src/ImageProcessorCore - Copy/ImageProcessor.cs deleted file mode 100644 index e7057a3f9..000000000 --- a/src/ImageProcessorCore - Copy/ImageProcessor.cs +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading; - - /// - /// Allows the application of processors to images. - /// - public abstract class ImageProcessor : IImageProcessor - { - /// - public event ProgressEventHandler OnProgress; - - /// - /// The number of rows processed by a derived class. - /// - private int numRowsProcessed; - - /// - /// The total number of rows that will be processed by a derived class. - /// - private int totalRows; - - /// - public void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle) - where TPackedVector : IPackedVector - { - try - { - this.OnApply(target, source, target.Bounds, sourceRectangle); - - this.numRowsProcessed = 0; - this.totalRows = sourceRectangle.Height; - - 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)) - where TPackedVector : IPackedVector - { - try - { - TPackedVector[] pixels = new TPackedVector[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.numRowsProcessed = 0; - this.totalRows = targetRectangle.Height; - - 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); - } - } - - /// - /// 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) - where TPackedVector : IPackedVector - { - } - - /// - /// Applies the process to the specified portion of the specified at the specified location - /// and with the specified size. - /// - /// The type of pixels contained within the image. - /// 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. - /// - protected abstract void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) where TPackedVector : IPackedVector; - - /// - /// This method is called after the process is applied to prepare the processor. - /// - /// The type of pixels contained within the image. - /// 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) - where TPackedVector : IPackedVector - { - } - - /// - /// Must be called by derived classes after processing a single row. - /// - protected void OnRowProcessed() - { - if (this.OnProgress != null) - { - int currThreadNumRows = Interlocked.Add(ref this.numRowsProcessed, 1); - - // Multi-pass filters process multiple times more rows than totalRows, so update totalRows on the fly - if (currThreadNumRows > this.totalRows) - { - this.totalRows = currThreadNumRows; - } - - // Report progress. This may be on the client's thread, or on a Task library thread. - this.OnProgress(this, new ProgressEventArgs { RowsProcessed = currThreadNumRows, TotalRows = this.totalRows }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/ImageProcessorCore.xproj b/src/ImageProcessorCore - Copy/ImageProcessorCore.xproj deleted file mode 100644 index ffe5b1cea..000000000 --- a/src/ImageProcessorCore - Copy/ImageProcessorCore.xproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 2aa31a1f-142c-43f4-8687-09abca4b3a26 - ImageProcessorCore - .\obj - .\bin\ - v4.5.1 - - - 2.0 - - - True - - - \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/ImageProperty.cs b/src/ImageProcessorCore - Copy/ImageProperty.cs deleted file mode 100644 index 1d8f5bb8e..000000000 --- a/src/ImageProcessorCore - Copy/ImageProperty.cs +++ /dev/null @@ -1,153 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -// -// 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. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - 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 struct ImageProperty : IEquatable - { - /// - /// Initializes a new instance of the struct. - /// - /// - /// The name of the property. - /// - /// - /// The value of the property. - /// - public ImageProperty(string name, string value) - { - 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; } - - /// - /// 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 left.Equals(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 !left.Equals(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) - { - if (!(obj is ImageProperty)) - { - return false; - } - - ImageProperty other = (ImageProperty)obj; - - return other.Name == this.Name && other.Value == this.Value; - } - - /// - /// 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(); - 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) - { - return this.Name.Equals(other.Name) && this.Value.Equals(other.Value); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Numerics/Ellipse.cs b/src/ImageProcessorCore - Copy/Numerics/Ellipse.cs deleted file mode 100644 index 5d87d1247..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Numerics/Point.cs b/src/ImageProcessorCore - Copy/Numerics/Point.cs deleted file mode 100644 index 818002f9e..000000000 --- a/src/ImageProcessorCore - Copy/Numerics/Point.cs +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageProcessorCore -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// 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); - - /// - /// The backing vector for SIMD support. - /// - private Vector2 backingVector; - - /// - /// 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.backingVector = new Vector2(x, y); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector representing the width and height. - /// - public Point(Vector2 vector) - { - this.backingVector = new Vector2(vector.X, vector.Y); - } - - /// - /// The x-coordinate of this . - /// - public int X - { - get - { - return (int)this.backingVector.X; - } - - set - { - this.backingVector.X = value; - } - } - - /// - /// The y-coordinate of this . - /// - public int Y - { - get - { - return (int)this.backingVector.Y; - } - - set - { - this.backingVector.Y = value; - } - } - - /// - /// 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 - /// - public static Point operator +(Point left, Point right) - { - return new Point(left.backingVector + right.backingVector); - } - - /// - /// 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 - /// - public static Point operator -(Point left, Point right) - { - return new Point(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 ==(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. - /// - public static bool operator !=(Point left, Point right) - { - return !left.Equals(right); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - public Vector2 ToVector2() - { - return new Vector2(this.X, this.Y); - } - - /// - /// 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, origin.backingVector); - } - - /// - /// 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(point.backingVector, 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(point.backingVector, 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, origin.backingVector); - } - - /// - /// 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(point.backingVector, 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(point.backingVector, CreateSkew(origin, degreesX, degreesY))); - } - - /// - 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.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(Point point) - { - return point.backingVector.GetHashCode(); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Numerics/Rectangle.cs b/src/ImageProcessorCore - Copy/Numerics/Rectangle.cs deleted file mode 100644 index 6fe2c3a49..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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; - } - - /// - /// The x-coordinate of this . - /// - public int X - { - get - { - return (int)this.backingVector.X; - } - - set - { - this.backingVector.X = value; - } - } - - /// - /// The y-coordinate of this . - /// - public int Y - { - get - { - return (int)this.backingVector.Y; - } - - set - { - this.backingVector.Y = value; - } - } - - /// - /// The width of this . - /// - public int Width - { - get - { - return (int)this.backingVector.Z; - } - - set - { - this.backingVector.Z = value; - } - } - - /// - /// 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/ImageProcessorCore - Copy/Numerics/Size.cs b/src/ImageProcessorCore - Copy/Numerics/Size.cs deleted file mode 100644 index 4b416b218..000000000 --- a/src/ImageProcessorCore - Copy/Numerics/Size.cs +++ /dev/null @@ -1,208 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// 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); - - /// - /// The backing vector for SIMD support. - /// - private Vector2 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The width of the size. - /// The height of the size. - public Size(int width, int height) - { - this.backingVector = new Vector2(width, height); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector representing the width and height. - /// - public Size(Vector2 vector) - { - this.backingVector = new Vector2(vector.X, vector.Y); - } - - /// - /// The width of this . - /// - public int Width - { - get - { - return (int)this.backingVector.X; - } - - set - { - this.backingVector.X = value; - } - } - - /// - /// The height of this . - /// - public int Height - { - get - { - return (int)this.backingVector.Y; - } - - set - { - this.backingVector.Y = value; - } - } - - /// - /// 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 - /// - public static Size operator +(Size left, Size right) - { - return new Size(left.backingVector + right.backingVector); - } - - /// - /// 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 - /// - public static Size operator -(Size left, Size right) - { - return new Size(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 ==(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. - /// - public static bool operator !=(Size left, Size right) - { - return !left.Equals(right); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - public Vector2 ToVector2() - { - return new Vector2(this.Width, this.Height); - } - - /// - 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} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Size) - { - return this.Equals((Size)obj); - } - - return false; - } - - /// - public bool Equals(Size 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(Size size) - { - return size.backingVector.GetHashCode(); - } - } -} diff --git a/src/ImageProcessorCore - Copy/PackedVector/Bgra32.cs b/src/ImageProcessorCore - Copy/PackedVector/Bgra32.cs deleted file mode 100644 index fc6a788b0..000000000 --- a/src/ImageProcessorCore - Copy/PackedVector/Bgra32.cs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.Numerics; - - /// - /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 1. - /// - public struct Bgra32 : IPackedVector, IEquatable - { - /// - /// Initializes a new instance of the struct. - /// - /// The blue component. - /// The green component. - /// The red component. - /// The alpha component. - public Bgra32(float b, float g, float r, float a) - { - Vector4 clamped = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, Vector4.One) * 255f; - this.PackedValue = Pack(ref clamped); - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// The vector containing the components for the packed vector. - /// - public Bgra32(Vector4 vector) - { - Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f; - this.PackedValue = Pack(ref clamped); - } - - /// - public uint PackedValue { get; set; } - - /// - /// 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.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 current left is equal to the parameter; otherwise, false. - /// - public static bool operator !=(Bgra32 left, Bgra32 right) - { - return left.PackedValue != right.PackedValue; - } - - /// - public void PackVector(Vector4 vector) - { - Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f; - this.PackedValue = Pack(ref clamped); - } - - /// - public void PackBytes(byte x, byte y, byte z, byte w) - { - Vector4 vector = new Vector4(x, y, z, w); - this.PackedValue = Pack(ref vector); - } - - /// - public Vector4 ToVector4() - { - return new Vector4( - this.PackedValue & 0xFF, - (this.PackedValue >> 8) & 0xFF, - (this.PackedValue >> 16) & 0xFF, - (this.PackedValue >> 24) & 0xFF) / 255f; - } - - /// - public byte[] ToBytes() - { - return new[] - { - (byte)(this.PackedValue & 0xFF), - (byte)((this.PackedValue >> 8) & 0xFF), - (byte)((this.PackedValue >> 16) & 0xFF), - (byte)((this.PackedValue >> 24) & 0xFF) - }; - } - - /// - public override bool Equals(object obj) - { - return (obj is Bgra32) && this.Equals((Bgra32)obj); - } - - /// - public bool Equals(Bgra32 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.GetHashCode(this); - } - - /// - /// Sets the packed representation from the given component values. - /// - /// - /// The vector containing the components for the packed vector. - /// - /// - /// The . - /// - private static uint Pack(ref Vector4 vector) - { - return (uint)Math.Round(vector.X) | - ((uint)Math.Round(vector.Y) << 8) | - ((uint)Math.Round(vector.Z) << 16) | - ((uint)Math.Round(vector.W) << 24); - } - - /// - /// 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(Bgra32 packed) - { - return packed.PackedValue.GetHashCode(); - } - } -} diff --git a/src/ImageProcessorCore - Copy/PackedVector/IPackedVector.cs b/src/ImageProcessorCore - Copy/PackedVector/IPackedVector.cs deleted file mode 100644 index 02e10cc3a..000000000 --- a/src/ImageProcessorCore - Copy/PackedVector/IPackedVector.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System.Numerics; - - /// - /// An interface that converts packed vector types to and from values, - /// allowing multiple encodings to be manipulated in a generic way. - /// - /// - /// The type of object representing the packed value. - /// - public interface IPackedVector : IPackedVector - where TPacked : struct - { - /// - /// Gets or sets the packed representation of the value. - /// Typically packed in least to greatest significance order. - /// - 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 pack. - void PackVector(Vector4 vector); - - /// - /// Sets the packed representation from a . - /// - /// The x-component. - /// The y-component. - /// The z-component. - /// The w-component. - void PackBytes(byte x, byte y, byte z, byte w); - - /// - /// Expands the packed representation into a . - /// The vector components are typically expanded in least to greatest significance order. - /// - /// The . - Vector4 ToVector4(); - - /// - /// Expands the packed representation into a . - /// The bytes are typically expanded in least to greatest significance order. - /// - /// The . - byte[] ToBytes(); - } -} diff --git a/src/ImageProcessorCore - Copy/PixelAccessor/Bgra32PixelAccessor.cs b/src/ImageProcessorCore - Copy/PixelAccessor/Bgra32PixelAccessor.cs deleted file mode 100644 index cecc148b9..000000000 --- a/src/ImageProcessorCore - Copy/PixelAccessor/Bgra32PixelAccessor.cs +++ /dev/null @@ -1,155 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - using System.Runtime.InteropServices; - - /// - /// Provides per-pixel access to an images pixels. - /// - /// - /// The image data is always stored in format, where the blue, green, red, and - /// alpha values are 8 bit unsigned bytes. - /// - public sealed unsafe class Bgra32PixelAccessor : IPixelAccessor - { - /// - /// The position of the first pixel in the bitmap. - /// - private Bgra32* 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 Bgra32PixelAccessor(IImageBase 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.pixelsBase = (Bgra32*)this.pixelsHandle.AddrOfPinnedObject().ToPointer(); - } - - /// - /// Finalizes an instance of the class. - /// - ~Bgra32PixelAccessor() - { - this.Dispose(); - } - - /// - /// Gets the width of the image. - /// - public int Width { get; } - - /// - /// Gets the height of the image. - /// - public int Height { get; } - - /// - /// Gets or sets the color of a 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 IPackedVector this[int x, int y] - { - get - { -#if DEBUG - if ((x < 0) || (x >= this.Width)) - { - throw new ArgumentOutOfRangeException(nameof(x), "Value cannot be less than zero or greater than the bitmap width."); - } - - if ((y < 0) || (y >= this.Height)) - { - throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height."); - } -#endif - return *(this.pixelsBase + ((y * this.Width) + x)); - } - - set - { -#if DEBUG - if ((x < 0) || (x >= this.Width)) - { - throw new ArgumentOutOfRangeException(nameof(x), "Value cannot be less than zero or greater than the bitmap width."); - } - - if ((y < 0) || (y >= this.Height)) - { - throw new ArgumentOutOfRangeException(nameof(y), "Value cannot be less than zero or greater than the bitmap height."); - } -#endif - *(this.pixelsBase + ((y * this.Width) + x)) = (Bgra32)value; - } - } - - /// - /// 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.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); - } - } -} diff --git a/src/ImageProcessorCore - Copy/PixelAccessor/IPixelAccessor.cs b/src/ImageProcessorCore - Copy/PixelAccessor/IPixelAccessor.cs deleted file mode 100644 index bf3a4067c..000000000 --- a/src/ImageProcessorCore - Copy/PixelAccessor/IPixelAccessor.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using System; - - /// - /// Encapsulates properties to provides per-pixel access to an images pixels. - /// - public interface IPixelAccessor : IDisposable - { - /// - /// Gets the width of the image in pixels. - /// - int Width { get; } - - /// - /// Gets the height of the image in pixels. - /// - 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. - IPackedVector this[int x, int y] - { - get; - set; - } - } -} diff --git a/src/ImageProcessorCore - Copy/ProgressEventArgs.cs b/src/ImageProcessorCore - Copy/ProgressEventArgs.cs deleted file mode 100644 index 0f4c027f5..000000000 --- a/src/ImageProcessorCore - Copy/ProgressEventArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Properties/AssemblyInfo.cs b/src/ImageProcessorCore - Copy/Properties/AssemblyInfo.cs deleted file mode 100644 index ea81ff60c..000000000 --- a/src/ImageProcessorCore - Copy/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Resources; -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("ImageProcessorCore")] -[assembly: AssemblyDescription("A cross-platform library for processing of image files written in C#")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("James Jackson-South")] -[assembly: AssemblyProduct("ImageProcessorCore")] -[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")] - -// Ensure the internals can be tested. -[assembly: InternalsVisibleTo("ImageProcessorCore.Benchmarks")] -[assembly: InternalsVisibleTo("ImageProcessorCore.Tests")] diff --git a/src/ImageProcessorCore - Copy/Quantizers/IQuantizer.cs b/src/ImageProcessorCore - Copy/Quantizers/IQuantizer.cs deleted file mode 100644 index 3196ebf9f..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/IQuantizer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Quantizers -{ - /// - /// Provides methods for allowing quantization of images pixels. - /// - public interface IQuantizer - { - /// - /// Gets or sets the transparency threshold. - /// - byte Threshold { get; set; } - - /// - /// 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); - } -} diff --git a/src/ImageProcessorCore - Copy/Quantizers/Octree/OctreeQuantizer.cs b/src/ImageProcessorCore - Copy/Quantizers/Octree/OctreeQuantizer.cs deleted file mode 100644 index c0c900145..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/Octree/OctreeQuantizer.cs +++ /dev/null @@ -1,534 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Quantizers -{ - using System; - using System.Collections.Generic; - - /// - /// Encapsulates methods to calculate the colour palette if an image using an Octree pattern. - /// - /// - public sealed class OctreeQuantizer : Quantizer - { - /// - /// 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, 255); - - 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(Bgra32 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(Bgra32 pixel) - { - // The color at [maxColors] is set to transparent - byte paletteIndex = (byte)this.colors; - - // Get the palette index if it's transparency meets criterea. - if (pixel.A > this.Threshold) - { - paletteIndex = (byte)this.octree.GetPaletteIndex(pixel); - } - - return paletteIndex; - } - - /// - /// Retrieve the palette for the quantized image. - /// - /// - /// The new color palette - /// - protected override List GetPalette() - { - // First off convert the Octree to maxColors colors - List palette = this.octree.Palletize(Math.Max(this.colors, 1)); - - palette.Add(Bgra32.Empty); - this.TransparentIndex = this.colors; - - return palette; - } - - /// - /// 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 = { 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 int 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 = 0; - 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(Bgra32 pixel) - { - // Check if this request is for the same color as the last - if (this.previousColor == pixel.Bgra) - { - // 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 = pixel.Bgra; - this.root.AddColor(pixel, this.maxColorBits, 0, this); - } - else - { - // Just update the previous node - this.previousNode.Increment(pixel); - } - } - else - { - this.previousColor = pixel.Bgra; - 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(Bgra32 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; - - /// - /// 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 = 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(Bgra32 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; - int index = ((pixel.R & Mask[level]) >> (shift - 2)) | - ((pixel.G & Mask[level]) >> (shift - 1)) | - ((pixel.B & Mask[level]) >> 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 = 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.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(); - - // And set the color of the palette entry - palette.Add(new Bgra32(b, g, r)); - } - 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(Bgra32 pixel, int level) - { - int index = this.paletteIndex; - - if (!this.leaf) - { - int shift = 7 - level; - int pixelIndex = ((pixel.R & Mask[level]) >> (shift - 2)) | - ((pixel.G & Mask[level]) >> (shift - 1)) | - ((pixel.B & Mask[level]) >> shift); - - if (this.children[pixelIndex] != null) - { - index = this.children[pixelIndex].GetPaletteIndex(pixel, level + 1); - } - else - { - throw new Exception("Didn't expect this!"); - } - } - - return index; - } - - /// - /// Increment the pixel count and add to the color information - /// - /// - /// The pixel to add. - /// - public void Increment(Bgra32 pixel) - { - this.pixelCount++; - this.red += pixel.R; - this.green += pixel.G; - this.blue += pixel.B; - } - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Quantizers/Octree/Quantizer.cs b/src/ImageProcessorCore - Copy/Quantizers/Octree/Quantizer.cs deleted file mode 100644 index 40d281015..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/Octree/Quantizer.cs +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Quantizers -{ - using System.Collections.Generic; - using System.Threading.Tasks; - - /// - /// Encapsulates methods to calculate the color palette of an image. - /// - public abstract class Quantizer : IQuantizer - { - /// - /// 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; - } - - /// - /// Gets or sets the transparency index. - /// - public int TransparentIndex { get; protected set; } = -1; - - /// - public byte Threshold { get; set; } - - /// - 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, this.TransparentIndex); - } - - /// - /// 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, - y => - { - for (int x = 0; x < source.Width; x++) - { - Bgra32 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(Bgra32 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(Bgra32 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/ImageProcessorCore - Copy/Quantizers/Palette/PaletteQuantizer.cs b/src/ImageProcessorCore - Copy/Quantizers/Palette/PaletteQuantizer.cs deleted file mode 100644 index db2a4c59c..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/Palette/PaletteQuantizer.cs +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.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. - /// - /// - public class PaletteQuantizer : Quantizer - { - /// - /// A lookup table for colors - /// - private readonly ConcurrentDictionary colorMap = new ConcurrentDictionary(); - - /// - /// List of all colors in the palette - /// - private Bgra32[] 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(Color[] palette = null) - : base(true) - { - if (palette == null) - { - List safe = ColorConstants.WebSafeColors.Select(c => (Bgra32)c).ToList(); - safe.Insert(0, Bgra32.Empty); - this.colors = safe.ToArray(); - } - else - { - this.colors = palette.Select(c => (Bgra32)c).ToArray(); - } - } - - /// - 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(Bgra32 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. - // Firstly check the alpha value - if less than the threshold, lookup the transparent color - if (!(pixel.A > this.Threshold)) - { - // Transparent. Lookup the first color with an alpha value of 0 - for (int index = 0; index < this.colors.Length; index++) - { - if (this.colors[index].A == 0) - { - colorIndex = (byte)index; - this.TransparentIndex = colorIndex; - break; - } - } - } - else - { - // Not transparent... - int leastDistance = int.MaxValue; - int red = pixel.R; - int green = pixel.G; - int blue = pixel.B; - - // Loop through the entire palette, looking for the closest color match - for (int index = 0; index < this.colors.Length; index++) - { - Bgra32 paletteColor = this.colors[index]; - - int redDistance = paletteColor.R - red; - int greenDistance = paletteColor.G - green; - int blueDistance = paletteColor.B - blue; - - int distance = (redDistance * redDistance) + - (greenDistance * greenDistance) + - (blueDistance * blueDistance); - - 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(); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Quantizers/QuantizedImage.cs b/src/ImageProcessorCore - Copy/Quantizers/QuantizedImage.cs deleted file mode 100644 index fdf93abd3..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/QuantizedImage.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Quantizers -{ - using System; - using System.Threading.Tasks; - - /// - /// Represents a quantized image where the pixels indexed by a color palette. - /// - public class QuantizedImage - { - /// - /// Initializes a new instance of the class. - /// - /// The image width. - /// The image height. - /// The color palette. - /// The quantized pixels. - /// The transparency index. - public QuantizedImage(int width, int height, Bgra32[] palette, byte[] pixels, int transparentIndex = -1) - { - 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; - this.TransparentIndex = transparentIndex; - } - - /// - /// 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 Bgra32[] Palette { get; } - - /// - /// Gets the pixels of this . - /// - public byte[] Pixels { get; } - - /// - /// Gets the transparent index - /// - public int TransparentIndex { 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; - float[] bgraPixels = new float[pixelCount * 4]; - - Parallel.For(0, pixelCount, - i => - { - int offset = i * 4; - Color color = this.Palette[Math.Min(palletCount, this.Pixels[i])]; - bgraPixels[offset] = color.R; - bgraPixels[offset + 1] = color.G; - bgraPixels[offset + 2] = color.B; - bgraPixels[offset + 3] = color.A; - }); - - image.SetPixels(this.Width, this.Height, bgraPixels); - return image; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Quantizers/Wu/Box.cs b/src/ImageProcessorCore - Copy/Quantizers/Wu/Box.cs deleted file mode 100644 index b9300b087..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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/ImageProcessorCore - Copy/Quantizers/Wu/WuQuantizer.cs b/src/ImageProcessorCore - Copy/Quantizers/Wu/WuQuantizer.cs deleted file mode 100644 index c06262503..000000000 --- a/src/ImageProcessorCore - Copy/Quantizers/Wu/WuQuantizer.cs +++ /dev/null @@ -1,786 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Quantizers -{ - using System; - using System.Collections.Generic; - 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. - /// - /// - public sealed class WuQuantizer : IQuantizer - { - /// - /// 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 byte Threshold { get; set; } - - /// - 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 image. - private void Build3DHistogram(PixelAccessor image) - { - for (int y = 0; y < image.Height; y++) - { - for (int x = 0; x < image.Width; x++) - { - Bgra32 color = image[x, y]; - - 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 transparentIndex = -1; - 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) - { - byte r = (byte)(Volume(cube[k], this.vmr) / weight); - byte g = (byte)(Volume(cube[k], this.vmg) / weight); - byte b = (byte)(Volume(cube[k], this.vmb) / weight); - byte a = (byte)(Volume(cube[k], this.vma) / weight); - - Bgra32 color = new Bgra32(b, g, r, a); - - if (color == Bgra32.Empty) - { - transparentIndex = k; - } - - pallette.Add(color); - } - else - { - pallette.Add(Bgra32.Empty); - transparentIndex = k; - } - } - - Parallel.For( - 0, - height, - y => - { - for (int x = 0; x < width; x++) - { - Bgra32 color = imagePixels[x, y]; - int a = color.A >> (8 - IndexAlphaBits); - int r = color.R >> (8 - IndexBits); - int g = color.G >> (8 - IndexBits); - int b = color.B >> (8 - IndexBits); - - if (transparentIndex > -1 && color.A <= this.Threshold) - { - pixels[(y * width) + x] = (byte)transparentIndex; - continue; - } - - 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, transparentIndex); - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Samplers/Crop.cs b/src/ImageProcessorCore - Copy/Samplers/Crop.cs deleted file mode 100644 index 239fd63f1..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Crop.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Crops an image to the given width and height. - /// - /// The image to resize. - /// The target image width. - /// The target image height. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Crop(this Image source, int width, int height, ProgressEventHandler progressHandler = null) - { - return Crop(source, width, height, source.Bounds, progressHandler); - } - - /// - /// 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 image to crop. - /// The target image width. - /// The target image height. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Crop(this Image source, int width, int height, Rectangle sourceRectangle, ProgressEventHandler progressHandler = null) - { - 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(); - processor.OnProgress += progressHandler; - - try - { - return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/EntropyCrop.cs b/src/ImageProcessorCore - Copy/Samplers/EntropyCrop.cs deleted file mode 100644 index 55284668c..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/EntropyCrop.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Crops an image to the area of greatest entropy. - /// - /// The image to crop. - /// The threshold for entropic density. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image EntropyCrop(this Image source, float threshold = .5f, ProgressEventHandler progressHandler = null) - { - EntropyCropProcessor processor = new EntropyCropProcessor(threshold); - processor.OnProgress += progressHandler; - - try - { - return source.Process(source.Width, source.Height, source.Bounds, Rectangle.Empty, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Options/AnchorPosition.cs b/src/ImageProcessorCore - Copy/Samplers/Options/AnchorPosition.cs deleted file mode 100644 index af840b292..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Samplers/Options/FlipType.cs b/src/ImageProcessorCore - Copy/Samplers/Options/FlipType.cs deleted file mode 100644 index c9b21a37e..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Samplers/Options/ResizeHelper.cs b/src/ImageProcessorCore - Copy/Samplers/Options/ResizeHelper.cs deleted file mode 100644 index a80ea4777..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Options/ResizeHelper.cs +++ /dev/null @@ -1,430 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 source image. - /// The resize options. - /// - /// The . - /// - public static Rectangle CalculateTargetLocationAndBounds(ImageBase source, ResizeOptions options) - { - 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 CalculateStretchRectangle(source, options); - } - } - - /// - /// Calculates the target rectangle for crop mode. - /// - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateCropRectangle(ImageBase source, ResizeOptions options) - { - 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 source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculatePadRectangle(ImageBase source, ResizeOptions options) - { - 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 source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateBoxPadRectangle(ImageBase source, ResizeOptions options) - { - 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 source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateMaxRectangle(ImageBase source, ResizeOptions options) - { - 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 source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateMinRectangle(ImageBase source, ResizeOptions options) - { - 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); - } - - /// - /// Calculates the target rectangle for stretch mode. - /// - /// The source image. - /// The resize options. - /// - /// The . - /// - private static Rectangle CalculateStretchRectangle(ImageBase source, ResizeOptions options) - { - return new Rectangle(0, 0, options.Size.Width, options.Size.Height); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Options/ResizeMode.cs b/src/ImageProcessorCore - Copy/Samplers/Options/ResizeMode.cs deleted file mode 100644 index a0ce94341..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Samplers/Options/ResizeOptions.cs b/src/ImageProcessorCore - Copy/Samplers/Options/ResizeOptions.cs deleted file mode 100644 index 82db8ed86..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - 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/ImageProcessorCore - Copy/Samplers/Options/RotateType.cs b/src/ImageProcessorCore - Copy/Samplers/Options/RotateType.cs deleted file mode 100644 index 43644de85..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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, - - /// - /// Rotate the image by 180 degrees clockwise. - /// - Rotate180, - - /// - /// Rotate the image by 270 degrees clockwise. - /// - Rotate270 - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Pad.cs b/src/ImageProcessorCore - Copy/Samplers/Pad.cs deleted file mode 100644 index de973d345..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Pad.cs +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Evenly pads an image to fit the new dimensions. - /// - /// The source image to pad. - /// The new width. - /// The new height. - /// A delegate which is called as progress is made processing the image. - /// The . - public static Image Pad(this Image source, int width, int height, ProgressEventHandler progressHandler = null) - { - ResizeOptions options = new ResizeOptions - { - Size = new Size(width, height), - Mode = ResizeMode.BoxPad, - Sampler = new NearestNeighborResampler() - }; - - return Resize(source, options, progressHandler); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/CropProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/CropProcessor.cs deleted file mode 100644 index adcd3c180..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/CropProcessor.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Threading.Tasks; - - /// - /// Provides methods to allow the cropping of an image. - /// - public class CropProcessor : ImageSampler - { - /// - protected 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, - y => - { - for (int x = startX; x < endX; x++) - { - targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY]; - } - - this.OnRowProcessed(); - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/EntropyCropProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/EntropyCropProcessor.cs deleted file mode 100644 index f9f8601f5..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/EntropyCropProcessor.cs +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Provides methods to allow the cropping of an image to preserve areas of highest - /// entropy. - /// - public class EntropyCropProcessor : ImageSampler - { - /// - /// 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; } - - /// - 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 ThresholdProcessor(.5f).Apply(temp, 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 float[rectangle.Width * rectangle.Height * 4]); - this.cropRectangle = rectangle; - } - - /// - protected 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; - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - y => - { - if (y >= targetY && y < targetBottom) - { - for (int x = startX; x < endX; x++) - { - targetPixels[x - startX, y - targetY] = sourcePixels[x, y]; - } - } - - this.OnRowProcessed(); - }); - } - } - - /// - 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); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/IImageSampler.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/IImageSampler.cs deleted file mode 100644 index 76a2c5a4d..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/IImageSampler.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Acts as a marker for generic parameters that require an image sampler. - /// - public interface IImageSampler : IImageProcessor - { - /// - /// 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/ImageProcessorCore - Copy/Samplers/Processors/ImageSampler.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/ImageSampler.cs deleted file mode 100644 index adfe77432..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/ImageSampler.cs +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - /// - /// Applies sampling methods to an image. - /// All processors requiring resampling or resizing should inherit from this. - /// - public abstract class ImageSampler : ImageProcessor, IImageSampler - { - /// - public virtual bool Compand { get; set; } = false; - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/Matrix3x2Processor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/Matrix3x2Processor.cs deleted file mode 100644 index e9b0441e3..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/Matrix3x2Processor.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - - /// - /// Provides methods to transform an image using a . - /// - public abstract class Matrix3x2Processor : ImageSampler - { - /// - /// 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 float[rectangle.Width * rectangle.Height * 4]); - } - } - - /// - /// 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 / 2f, -target.Height / 2f); - Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width / 2f, source.Height / 2f); - return (translationToTargetCenter * matrix) * translateToSourceCenter; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/ResizeProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/ResizeProcessor.cs deleted file mode 100644 index 95ead2bf0..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/ResizeProcessor.cs +++ /dev/null @@ -1,362 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the resizing of images using various algorithms. - /// - public class ResizeProcessor : ImageSampler - { - /// - /// The image used for storing the first pass pixels. - /// - private Image firstPass; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The sampler to perform the resize operation. - /// - public ResizeProcessor(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); - } - - this.firstPass = new Image(target.Width, source.Height); - } - - /// - protected 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; - bool compand = this.Compand; - - 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( - startY, - endY, - y => - { - if (targetY <= y && y < targetBottom) - { - // Y coordinates of source points - int originY = (int)((y - startY) * heightFactor); - - for (int x = startX; x < endX; x++) - { - if (targetX <= x && x < targetRight) - { - // X coordinates of source points - int originX = (int)((x - startX) * widthFactor); - - targetPixels[x, y] = sourcePixels[originX, originY]; - } - } - - this.OnRowProcessed(); - } - }); - } - - // 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. - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor firstPassPixels = this.firstPass.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - sourceHeight, - y => - { - for (int x = startX; x < endX; x++) - { - if (x >= 0 && x < width) - { - // Ensure offsets are normalised for cropping and padding. - int offsetX = x - startX; - float sum = this.HorizontalWeights[offsetX].Sum; - Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values; - - // Destination color components - Color destination = new Color(); - - for (int i = 0; i < sum; i++) - { - Weight xw = horizontalValues[i]; - int originX = xw.Index; - Color sourceColor = compand - ? Color.Expand(sourcePixels[originX, y]) - : sourcePixels[originX, y]; - - destination += sourceColor * xw.Value; - } - - if (compand) - { - destination = Color.Compress(destination); - } - - firstPassPixels[x, y] = destination; - } - } - }); - - // Now process the rows. - Parallel.For( - startY, - endY, - y => - { - if (y >= 0 && y < height) - { - // Ensure offsets are normalised for cropping and padding. - int offsetY = y - startY; - float sum = this.VerticalWeights[offsetY].Sum; - Weight[] verticalValues = this.VerticalWeights[offsetY].Values; - - for (int x = 0; x < width; x++) - { - // Destination color components - Color destination = new Color(); - - for (int i = 0; i < sum; i++) - { - Weight yw = verticalValues[i]; - int originY = yw.Index; - Color sourceColor = compand - ? Color.Expand(firstPassPixels[x, originY]) - : firstPassPixels[x, originY]; - - destination += sourceColor * yw.Value; - } - - if (compand) - { - destination = Color.Compress(destination); - } - - targetPixels[x, y] = destination; - } - } - - this.OnRowProcessed(); - }); - - } - } - - /// - 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 scale = (float)destinationSize / sourceSize; - IResampler sampler = this.Sampler; - float radius = sampler.Radius; - double left; - double right; - float weight; - int index; - int sum; - - Weights[] result = new Weights[destinationSize]; - - // When shrinking, broaden the effective kernel support so that we still - // visit every source pixel. - if (scale < 1) - { - float width = radius / scale; - float filterScale = 1 / scale; - - // Make the weights slices, one source for each column or row. - for (int i = 0; i < destinationSize; i++) - { - float centre = i / scale; - left = Math.Ceiling(centre - width); - right = Math.Floor(centre + width); - - result[i] = new Weights - { - Values = new Weight[(int)(right - left + 1)] - }; - - for (double j = left; j <= right; j++) - { - weight = sampler.GetValue((float)((centre - j) / filterScale)) / filterScale; - if (j < 0) - { - index = (int)-j; - } - else if (j >= sourceSize) - { - index = (int)((sourceSize - j) + sourceSize - 1); - } - else - { - index = (int)j; - } - - sum = (int)result[i].Sum++; - result[i].Values[sum] = new Weight(index, weight); - } - } - } - else - { - // Make the weights slices, one source for each column or row. - for (int i = 0; i < destinationSize; i++) - { - float centre = i / scale; - left = Math.Ceiling(centre - radius); - right = Math.Floor(centre + radius); - result[i] = new Weights - { - Values = new Weight[(int)(right - left + 1)] - }; - - for (double j = left; j <= right; j++) - { - weight = sampler.GetValue((float)(centre - j)); - if (j < 0) - { - index = (int)-j; - } - else if (j >= sourceSize) - { - index = (int)((sourceSize - j) + sourceSize - 1); - } - else - { - index = (int)j; - } - - sum = (int)result[i].Sum++; - result[i].Values[sum] = new Weight(index, weight); - } - } - } - - return result; - } - - /// - /// Represents the weight to be added to a scaled pixel. - /// - protected struct Weight - { - /// - /// Initializes a new instance of the struct. - /// - /// 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 the result of the interpolation algorithm. - /// - public float Value { get; } - } - - /// - /// Represents a collection of weights and their sum. - /// - protected class Weights - { - /// - /// Gets or sets the values. - /// - public Weight[] Values { get; set; } - - /// - /// Gets or sets the sum. - /// - public float Sum { get; set; } - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/RotateFlipProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/RotateFlipProcessor.cs deleted file mode 100644 index 6ef8866ba..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/RotateFlipProcessor.cs +++ /dev/null @@ -1,231 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the rotation and flipping of an image around its center point. - /// - public class RotateFlipProcessor : ImageSampler - { - /// - /// Initializes a new instance of the class. - /// - /// The used to perform rotation. - /// The used to perform flipping. - public RotateFlipProcessor(RotateType rotateType, FlipType flipType) - { - this.RotateType = rotateType; - this.FlipType = flipType; - } - - /// - /// Gets the used to perform flipping. - /// - public FlipType FlipType { get; } - - /// - /// Gets the used to perform rotation. - /// - public RotateType RotateType { get; } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - switch (this.RotateType) - { - case RotateType.Rotate90: - this.Rotate90(target, source); - break; - case RotateType.Rotate180: - this.Rotate180(target, source); - break; - case RotateType.Rotate270: - this.Rotate270(target, source); - break; - default: - target.ClonePixels(target.Width, target.Height, source.Pixels); - break; - } - - 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; - } - } - - /// - /// 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, - y => - { - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - newX = height - newX - 1; - int newY = width - x - 1; - newY = width - newY - 1; - tempPixels[newX, newY] = sourcePixels[x, y]; - } - - this.OnRowProcessed(); - }); - } - - 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, - y => - { - for (int x = 0; x < width; x++) - { - int newX = width - x - 1; - int newY = height - y - 1; - targetPixels[newX, newY] = sourcePixels[x, y]; - } - - this.OnRowProcessed(); - }); - } - } - - /// - /// 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, - y => - { - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - tempPixels[newX, x] = sourcePixels[x, y]; - } - - this.OnRowProcessed(); - }); - } - - target.SetPixels(height, width, temp.Pixels); - } - - /// - /// 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 * .5); - ImageBase 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, - 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]; - } - - this.OnRowProcessed(); - }); - } - } - - /// - /// 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 / 2d); - ImageBase 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, - 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]; - } - - this.OnRowProcessed(); - }); - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/RotateProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/RotateProcessor.cs deleted file mode 100644 index 7aafe0e08..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/RotateProcessor.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the rotating of images. - /// - public class RotateProcessor : Matrix3x2Processor - { - /// - /// 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) - { - processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle); - if (this.Expand) - { - CreateNewTarget(target, sourceRectangle, processMatrix); - } - } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - target.Height, - y => - { - for (int x = 0; x < target.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]; - } - } - - OnRowProcessed(); - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore - Copy/Samplers/Processors/SkewProcessor.cs deleted file mode 100644 index 02d5dd9e4..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Processors/SkewProcessor.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore.Processors -{ - using System.Numerics; - using System.Threading.Tasks; - - /// - /// Provides methods that allow the skewing of images. - /// - public class SkewProcessor : Matrix3x2Processor - { - /// - /// 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); - } - } - - /// - protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - target.Height, - y => - { - for (int x = 0; x < target.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]; - } - } - - OnRowProcessed(); - }); - } - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/BicubicResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/BicubicResampler.cs deleted file mode 100644 index 8aecac7a6..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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) - { - // The coefficient. - float a = -0.5f; - - if (x < 0) - { - x = -x; - } - - float result = 0; - - if (x <= 1) - { - result = (((1.5f * x) - 2.5f) * x * x) + 1; - } - else if (x < 2) - { - result = (((((a * x) + 2.5f) * x) - 4) * x) + 2; - } - - return result; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/BoxResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/BoxResampler.cs deleted file mode 100644 index b1234e415..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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.5 && x <= 0.5) - { - return 1; - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/CatmullRomResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/CatmullRomResampler.cs deleted file mode 100644 index 0b5031df8..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 = 1 / 2f; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/HermiteResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/HermiteResampler.cs deleted file mode 100644 index 49193a3de..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore.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 = 0; - const float C = 0; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/IResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/IResampler.cs deleted file mode 100644 index 0dea58440..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos3Resampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos3Resampler.cs deleted file mode 100644 index a78b6c066..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 < 0) - { - x = -x; - } - - if (x < 3) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3f); - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos5Resampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos5Resampler.cs deleted file mode 100644 index 05af2dd7f..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 < 0) - { - x = -x; - } - - if (x < 5) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 5f); - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos8Resampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/Lanczos8Resampler.cs deleted file mode 100644 index 8c9a9237d..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 < 0) - { - x = -x; - } - - if (x < 8) - { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / 8f); - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/MitchellNetravaliResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/MitchellNetravaliResampler.cs deleted file mode 100644 index f609f2645..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 = 1 / 3f; - const float C = 1 / 3f; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/NearestNeighborResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/NearestNeighborResampler.cs deleted file mode 100644 index 58b6a9d58..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxResampler.cs deleted file mode 100644 index caead12d5..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// The function implements the Robidoux algorithm. - /// - /// - public class RobidouxResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.3782158F; - const float C = 0.3108921F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSharpResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSharpResampler.cs deleted file mode 100644 index 633503cd1..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// The function implements the Robidoux Sharp algorithm. - /// - /// - public class RobidouxSharpResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.26201451F; - const float C = 0.36899274F; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSoftResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSoftResampler.cs deleted file mode 100644 index 8706f492b..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Resamplers/RobidouxSoftResampler.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - /// - /// The function implements the Robidoux Soft algorithm. - /// - /// - public class RobidouxSoftResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 0.6796f; - const float C = 0.1602f; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/SplineResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/SplineResampler.cs deleted file mode 100644 index 55ef5656a..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// The function implements the spline algorithm. - /// - /// - public class SplineResampler : IResampler - { - /// - public float Radius => 2; - - /// - public float GetValue(float x) - { - const float B = 1; - const float C = 0; - - return ImageMaths.GetBcValue(x, B, C); - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/TriangleResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/TriangleResampler.cs deleted file mode 100644 index cb404b736..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// 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 < 0) - { - x = -x; - } - - if (x < 1) - { - return 1 - x; - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resamplers/WelchResampler.cs b/src/ImageProcessorCore - Copy/Samplers/Resamplers/WelchResampler.cs deleted file mode 100644 index 3ecaa6a74..000000000 --- a/src/ImageProcessorCore - Copy/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 ImageProcessorCore -{ - /// - /// The function implements the welch algorithm. - /// - /// - public class WelchResampler : IResampler - { - /// - public float Radius => 3; - - /// - public float GetValue(float x) - { - if (x < 0) - { - x = -x; - } - - if (x < 3) - { - return ImageMaths.SinC(x) * (1.0f - (x * x / 9.0f)); - } - - return 0; - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Resize.cs b/src/ImageProcessorCore - Copy/Samplers/Resize.cs deleted file mode 100644 index 2eadd7a11..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Resize.cs +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// ------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Resizes an image in accordance with the given . - /// - /// The image to resize. - /// The resize options. - /// A delegate which is called as progress is made processing the image. - /// 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, ProgressEventHandler progressHandler = null) - { - // 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, progressHandler); - } - - /// - /// Resizes an image to the given width and height. - /// - /// The image to resize. - /// The target image width. - /// The target image height. - /// A delegate which is called as progress is made processing the image. - /// 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, ProgressEventHandler progressHandler = null) - { - return Resize(source, width, height, new BicubicResampler(), false, progressHandler); - } - - /// - /// Resizes an image to the given width and height. - /// - /// 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. - /// A delegate which is called as progress is made processing the image. - /// 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, ProgressEventHandler progressHandler = null) - { - return Resize(source, width, height, new BicubicResampler(), compand, progressHandler); - } - - /// - /// Resizes an image to the given width and height with the given sampler. - /// - /// 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. - /// A delegate which is called as progress is made processing the image. - /// 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, ProgressEventHandler progressHandler = null) - { - return Resize(source, width, height, sampler, source.Bounds, new Rectangle(0, 0, width, height), compand, progressHandler); - } - - /// - /// Resizes an image to the given width and height with the given sampler and - /// source rectangle. - /// - /// 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. - /// A delegate which is called as progress is made processing the image. - /// 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, ProgressEventHandler progressHandler = null) - { - 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)); - - ResizeProcessor processor = new ResizeProcessor(sampler) { Compand = compand }; - processor.OnProgress += progressHandler; - - try - { - return source.Process(width, height, sourceRectangle, targetRectangle, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Rotate.cs b/src/ImageProcessorCore - Copy/Samplers/Rotate.cs deleted file mode 100644 index fa30d9d34..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Rotate.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 image to rotate. - /// The angle in degrees to perform the rotation. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Rotate(this Image source, float degrees, ProgressEventHandler progressHandler = null) - { - return Rotate(source, degrees, true, progressHandler); - } - - /// - /// Rotates an image by the given angle in degrees. - /// - /// The image to rotate. - /// The angle in degrees to perform the rotation. - /// Whether to expand the image to fit the rotated result. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Rotate(this Image source, float degrees, bool expand, ProgressEventHandler progressHandler = null) - { - RotateProcessor processor = new RotateProcessor { Angle = degrees, Expand = expand }; - processor.OnProgress += progressHandler; - - try - { - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/RotateFlip.cs b/src/ImageProcessorCore - Copy/Samplers/RotateFlip.cs deleted file mode 100644 index 93449bcd0..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/RotateFlip.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - using Processors; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Rotates and flips an image by the given instructions. - /// - /// The image to rotate, flip, or both. - /// The to perform the rotation. - /// The to perform the flip. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image RotateFlip(this Image source, RotateType rotateType, FlipType flipType, ProgressEventHandler progressHandler = null) - { - RotateFlipProcessor processor = new RotateFlipProcessor(rotateType, flipType); - processor.OnProgress += progressHandler; - - try - { - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/Samplers/Skew.cs b/src/ImageProcessorCore - Copy/Samplers/Skew.cs deleted file mode 100644 index 904f1d89d..000000000 --- a/src/ImageProcessorCore - Copy/Samplers/Skew.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageProcessorCore -{ - 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 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. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Skew(this Image source, float degreesX, float degreesY, ProgressEventHandler progressHandler = null) - { - return Skew(source, degreesX, degreesY, true, progressHandler); - } - - /// - /// Skews an image by the given angles in degrees. - /// - /// 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. - /// A delegate which is called as progress is made processing the image. - /// The - public static Image Skew(this Image source, float degreesX, float degreesY, bool expand, ProgressEventHandler progressHandler = null) - { - SkewProcessor processor = new SkewProcessor { AngleX = degreesX, AngleY = degreesY, Expand = expand }; - processor.OnProgress += progressHandler; - - try - { - return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor); - } - finally - { - processor.OnProgress -= progressHandler; - } - } - } -} diff --git a/src/ImageProcessorCore - Copy/project.json b/src/ImageProcessorCore - Copy/project.json deleted file mode 100644 index e3800d495..000000000 --- a/src/ImageProcessorCore - Copy/project.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "version": "1.0.0-*", - "title": "ImageProcessorCore", - "description": "A cross-platform library for processing of image files written in C#", - "authors": [ - "James Jackson-South and contributors" - ], - "packOptions": { - "projectUrl": "https://github.com/JimBobSquarePants/ImageProcessor", - "licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0", - "tags": [ - "Image Resize Crop Quality Gif Jpg Jpeg Bitmap Png Fluent Animated" - ] - }, - "buildOptions": { - "allowUnsafe": true, - "debugType": "portable" - }, - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tools": "4.0.1", - "System.IO": "4.1.0", - "System.IO.Compression": "4.1.0", - "System.Linq": "4.1.0", - "System.Numerics.Vectors": "4.1.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.InteropServices": "4.1.0", - "System.Text.Encoding.Extensions": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "System.Threading.Tasks.Parallel": "4.0.1" - }, - "frameworks": { - "netstandard1.1": {} - } -} \ No newline at end of file