Exemple #1
0
        /// <summary>
        /// Reduces the size and resolution of this <see cref="Image"/> by a factor of 4 by downsampling.
        /// </summary>
        /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param>
        /// <returns>
        /// The destination <see cref="Image"/>.
        /// </returns>
        /// <remarks>
        /// <para>If <paramref name="dst"/> is <b>null</b> the method creates new destination <see cref="Image"/> with dimensions of this <see cref="Image"/>.</para>
        /// <para>If <paramref name="dst"/> equals this <see cref="Image"/>, the operation is performed in-place.</para>
        /// <para>Conversely, the <paramref name="dst"/> is reallocated to the dimensions of this <see cref="Image"/>.</para>
        /// </remarks>
        public Image ScaleByDownsampling4(Image dst)
        {
            int width        = this.Width;
            int height       = this.Height;
            int bitsPerPixel = this.BitsPerPixel;
            int dstwidth     = width / 4;
            int dstheight    = height / 4;

            bool inplace = dst == this;

            dst = this.CreateTemplate(dst, dstwidth, dstheight, bitsPerPixel);

            switch (bitsPerPixel)
            {
            case 1:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        ulong * ptrsrc      = (ulong *)bitssrc;
                        ushort *ptrdst      = (ushort *)bitsdst;
                        int     stridesrc   = this.Stride;
                        int     stride16dst = dst.Stride * 4;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stridesrc, ptrdst += stride16dst)
                        {
                            for (int x = 0, xdst = 0, xsrc = 0; x < dstwidth; x += 16, xdst++, xsrc++)
                            {
                                ulong bits = ptrsrc[xsrc];
                                ptrdst[xdst] = (ushort)(
                                    (bits & 0x0001) |
                                    ((bits >> 3) & 0x0002) |
                                    ((bits >> 6) & 0x0004) |
                                    ((bits >> 9) & 0x0008) |
                                    ((bits >> 12) & 0x0010) |
                                    ((bits >> 15) & 0x0020) |
                                    ((bits >> 18) & 0x0040) |
                                    ((bits >> 21) & 0x0080) |
                                    ((bits >> 24) & 0x0100) |
                                    ((bits >> 27) & 0x0200) |
                                    ((bits >> 30) & 0x0400) |
                                    ((bits >> 33) & 0x0800) |
                                    ((bits >> 36) & 0x1000) |
                                    ((bits >> 39) & 0x2000) |
                                    ((bits >> 42) & 0x4000) |
                                    ((bits >> 45) & 0x8000));
                            }
                        }
                    }
                }

                break;

            case 2:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        ulong * ptrsrc      = (ulong *)bitssrc;
                        ushort *ptrdst      = (ushort *)bitsdst;
                        int     stridesrc   = this.Stride;
                        int     stride16dst = dst.Stride * 4;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stridesrc, ptrdst += stride16dst)
                        {
                            for (int x = 0, xdst = 0, xsrc = 0; x < dstwidth; x += 8, xdst++, xsrc++)
                            {
                                ulong bits = ptrsrc[xsrc];
                                ptrdst[xdst] = (ushort)(
                                    (bits & 0x0003) |
                                    ((bits >> 6) & 0x000c) |
                                    ((bits >> 12) & 0x0030) |
                                    ((bits >> 18) & 0x00c0) |
                                    ((bits >> 24) & 0x0300) |
                                    ((bits >> 30) & 0x0c00) |
                                    ((bits >> 36) & 0x3000) |
                                    ((bits >> 42) & 0xc000));
                            }
                        }
                    }
                }

                break;

            case 4:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        ulong * ptrsrc      = (ulong *)bitssrc;
                        ushort *ptrdst      = (ushort *)bitsdst;
                        int     stridesrc   = this.Stride;
                        int     stride16dst = dst.Stride * 4;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stridesrc, ptrdst += stride16dst)
                        {
                            for (int x = 0, xdst = 0, xsrc = 0; x < dstwidth; x += 4, xdst++, xsrc++)
                            {
                                ulong bits = ptrsrc[xsrc];
                                ptrdst[xdst] = (ushort)(
                                    (bits & 0x000f) |
                                    ((bits >> 12) & 0x00f0) |
                                    ((bits >> 24) & 0x0f00) |
                                    ((bits >> 36) & 0xf000));
                            }
                        }
                    }
                }

                break;

            case 8:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        byte *ptrsrc     = (byte *)bitssrc;
                        byte *ptrdst     = (byte *)bitsdst;
                        int   stride8src = this.Stride8;
                        int   stride8dst = dst.Stride8;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stride8src, ptrdst += stride8dst)
                        {
                            for (int xdst = 0, xsrc = 0; xdst < dstwidth; xdst++, xsrc += 4)
                            {
                                ptrdst[xdst] = ptrsrc[xsrc];
                            }
                        }
                    }
                }

                break;

            case 16:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        ushort *ptrsrc      = (ushort *)bitssrc;
                        ushort *ptrdst      = (ushort *)bitsdst;
                        int     stride16src = this.Stride * 4;
                        int     stride16dst = dst.Stride * 4;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stride16src, ptrdst += stride16dst)
                        {
                            for (int xdst = 0, xsrc = 0; xdst < dstwidth; xdst++, xsrc += 4)
                            {
                                ptrdst[xdst] = ptrsrc[xsrc];
                            }
                        }
                    }
                }

                break;

            case 24:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        byte *ptrsrc     = (byte *)bitssrc;
                        byte *ptrdst     = (byte *)bitsdst;
                        int   stride8src = this.Stride8;
                        int   stride8dst = dst.Stride8;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stride8src, ptrdst += stride8dst)
                        {
                            for (int xdst = 0, xsrc = 0; xdst < 3 * dstwidth; xdst += 3, xsrc += 4 * 3)
                            {
                                ptrdst[xdst + 0] = ptrsrc[xsrc + 0];
                                ptrdst[xdst + 1] = ptrsrc[xsrc + 1];
                                ptrdst[xdst + 2] = ptrsrc[xsrc + 2];
                            }
                        }
                    }
                }

                break;

            case 32:
                unsafe
                {
                    fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits)
                    {
                        uint *ptrsrc      = (uint *)bitssrc;
                        uint *ptrdst      = (uint *)bitsdst;
                        int   stride32src = this.Stride * 2;
                        int   stride32dst = dst.Stride * 2;

                        for (int ydst = 0; ydst < dstheight; ydst++, ptrsrc += 4 * stride32src, ptrdst += stride32dst)
                        {
                            for (int xdst = 0, xsrc = 0; xdst < dstwidth; xdst++, xsrc += 4)
                            {
                                ptrdst[xdst] = ptrsrc[xsrc];
                            }
                        }
                    }
                }

                break;

            default:
                throw new NotSupportedException(string.Format(
                                                    CultureInfo.InvariantCulture,
                                                    Properties.Resources.E_UnsupportedDepth,
                                                    bitsPerPixel));
            }

            dst.SetResolution(this.HorizontalResolution / 4, this.VerticalResolution / 4);
            dst.AppendTransform(new MatrixTransform(0.25, 0.25));

            if (inplace)
            {
                this.Attach(dst);
                return(this);
            }

            return(dst);
        }