Exemplo n.º 1
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        /// <exception cref="InvalidImagePropertiesException">Texture size does not match image size.</exception>
        /// <exception cref="ApplicationException">Filters should not change image dimension.</exception>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get source image dimension
            int width  = sourceData.Width;
            int height = sourceData.Height;

            // if generator was specified, then generate a texture
            // otherwise use provided texture
            if (textureGenerator != null)
            {
                texture = textureGenerator.Generate(width, height);
            }
            else
            {
                // check existing texture
                if ((texture.GetLength(0) != height) || (texture.GetLength(1) != width))
                {
                    // sorry, but source image must have the same dimension as texture
                    throw new InvalidImagePropertiesException("Texture size does not match image size.");
                }
            }

            // apply first filter
            UnmanagedImage filteredImage1 = filter1.Apply(sourceData);

            // check size of the result image
            if ((width != filteredImage1.Width) || (height != filteredImage1.Height))
            {
                filteredImage1.Dispose( );
                throw new ApplicationException("Filters should not change image dimension.");
            }

            // convert 1st image to RGB if required
            if (filteredImage1.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                GrayscaleToRGB coloringFilter = new GrayscaleToRGB( );
                UnmanagedImage temp           = coloringFilter.Apply(filteredImage1);
                filteredImage1.Dispose( );
                filteredImage1 = temp;
            }

            UnmanagedImage filteredImage2 = null;

            // apply second filter, if it was specified
            if (filter2 != null)
            {
                filteredImage2 = filter2.Apply(sourceData);
                // check size of the result image
                if ((width != filteredImage2.Width) || (height != filteredImage2.Height))
                {
                    filteredImage1.Dispose( );
                    filteredImage2.Dispose( );
                    // we are not handling such situations yet
                    throw new ApplicationException("Filters should not change image dimension.");
                }

                // convert 2nd image to RGB if required
                if (filteredImage2.PixelFormat == PixelFormat.Format8bppIndexed)
                {
                    GrayscaleToRGB coloringFilter = new GrayscaleToRGB( );
                    UnmanagedImage temp           = coloringFilter.Apply(filteredImage2);
                    filteredImage2.Dispose( );
                    filteredImage2 = temp;
                }
            }

            // use source image as a second image, if second filter is not set
            if (filteredImage2 == null)
            {
                filteredImage2 = sourceData;
            }

            // do the job
            unsafe
            {
                byte *dst  = (byte *)destinationData.ImageData.ToPointer( );
                byte *src1 = (byte *)filteredImage1.ImageData.ToPointer( );
                byte *src2 = (byte *)filteredImage2.ImageData.ToPointer( );

                int dstOffset  = destinationData.Stride - 3 * width;
                int src1Offset = filteredImage1.Stride - 3 * width;
                int src2Offset = filteredImage2.Stride - 3 * width;

                if (preserveLevel != 0.0)
                {
                    // for each line
                    for (int y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (int x = 0; x < width; x++)
                        {
                            double t1 = texture[y, x];
                            double t2 = 1 - t1;

                            for (int i = 0; i < 3; i++, src1++, src2++, dst++)
                            {
                                *dst = (byte)Math.Min(255.0f,
                                                      filterLevel * (t1 * (*src1) + t2 * (*src2)) +
                                                      preserveLevel * (*src2));
                            }
                        }
                        src1 += src1Offset;
                        src2 += src2Offset;
                        dst  += dstOffset;
                    }
                }
                else
                {
                    // for each line
                    for (int y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (int x = 0; x < width; x++)
                        {
                            double t1 = texture[y, x];
                            double t2 = 1 - t1;

                            for (int i = 0; i < 3; i++, src1++, src2++, dst++)
                            {
                                *dst = (byte)Math.Min(255.0f, t1 * *src1 + t2 * *src2);
                            }
                        }
                        src1 += src1Offset;
                        src2 += src2Offset;
                        dst  += dstOffset;
                    }
                }
            }

            // dispose temp images
            filteredImage1.Dispose( );
            if (filteredImage2 != sourceData)
            {
                filteredImage2.Dispose( );
            }
        }