Beispiel #1
0
        /// <summary>
        /// Creates a new Bitmap with the resolution reduced by half in the vertical direction using
        /// the indicated method.  Source must be 1bppIndexed.  Source must be a standard Fax size.
        /// </summary>
        /// <param name="bmp">Source Bitmap.</param>
        /// <param name="scaleMethod">The scaling method.</param>
        /// <returns>The new bitmap in 1bppIndexed format.</returns>
        internal static Bitmap ConvertTiffHiToTiffLow(Bitmap bmp, HighToLowScaleMethod scaleMethod)
        {
            PaperSize paperSize = BitmapHelper.GetStandardPaperSize(bmp);

            //If the paper size is not standard then throw error
            if (paperSize == PaperSize.Undefined)
            {
                throw new Exception("Source bitmap returned an incorrect paper size.");
            }

            //If its not in 32bppArgb format then throw error
            if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
            {
                throw new Exception("Source format must be Format1bppIndexed.");
            }

            //If its already a low resolution, then copy and return.
            if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_LOW)
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            //No Scale requested.
            if (scaleMethod == HighToLowScaleMethod.NoScale)
            {
                return(BitmapHelper.CreateCopyExact(bmp));
            }

            //If its in tiff high resolution, then throw error
            if (bmp.VerticalResolution != ImageUtility.FAX_TIF_VER_RES_HI)
            {
                throw new Exception("Source resolution is not FAX_TIF_VER_RES_HI.");
            }

            Bitmap ret = BitmapHelper.CreateBitMap(paperSize, FaxQuality.Normal, PixelFormat.Format1bppIndexed);

            // Lock source bitmap in memory
            BitmapData sourceData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;

            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            bmp.UnlockBits(sourceData);

            // Lock destination bitmap in memory
            BitmapData destinationData = ret.LockBits(new Rectangle(0, 0, ret.Width, ret.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Create destination buffer
            imageSize = destinationData.Stride * destinationData.Height;
            byte[] destinationBuffer = new byte[imageSize];

            int nnx_ratio = (int)((sourceData.Stride << 16) / destinationData.Stride) + 1;
            int nny_ratio = (int)((sourceData.Height << 16) / destinationData.Height) + 1;

            int   A, B, C, D, x, y, index, gray;
            float x_ratio = ((float)(sourceData.Stride - 1)) / destinationData.Stride;
            float y_ratio = ((float)(sourceData.Height - 1)) / destinationData.Height;
            float x_diff, y_diff;
            int   offset = 0;

            for (int j = 0; j < destinationData.Height; j++)              //For every row
            {
                for (int i = 0; i < destinationData.Stride; i++)          //For each byte in row
                {
                    byte s1 = sourceBuffer[(j * 2) * destinationData.Stride + i];
                    byte s2 = sourceBuffer[((j * 2) + 1) * destinationData.Stride + i];
                    byte d1 = 0;

                    switch (scaleMethod)
                    {
                    case HighToLowScaleMethod.ORing:
                    {
                        d1 = (byte)(s1 | s2);
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.ANDing:
                    {
                        d1 = (byte)(s1 & s2);
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.Elimination:
                    {
                        d1 = s1;
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.Averaging:
                    {
                        //d1 = (byte)(s1 | s2);
                        //d1 = (byte)(s1 ^ s2);
                        d1 = (byte)((s1 + s2) / 2);
                        //int a1s1 = s1 >> 6 & 3;
                        //int a1s2 = s2 >> 6 & 3;
                        //int a2s1 = s1 >> 4 & 3;
                        //int a2s2 = s2 >> 4 & 3;
                        //int a3s1 = s1 >> 2 & 3;
                        //int a3s2 = s2 >> 2 & 3;
                        //int a4s1 = s1 & 3;
                        //int a4s2 = s2 & 3;
                        //d1 = (byte)(((a1s1 + a1s2) / 2 << 6) + ((a2s1 + a2s2) / 2 << 4) + ((a3s1 + a3s2) / 2 << 2) + ((a4s1 + a4s2) / 2));
                        destinationBuffer[j * destinationData.Stride + i] = d1;
                        break;
                    }

                    case HighToLowScaleMethod.NearestNeighbor:
                    {
                        int x2 = ((i * nnx_ratio) >> 16);
                        int y2 = ((j * nny_ratio) >> 16);

                        destinationBuffer[j * destinationData.Stride + i] = sourceBuffer[(y2 * sourceData.Stride) + x2];
                        break;
                    }

                    case HighToLowScaleMethod.Bilinear:
                    {
                        x      = (int)(x_ratio * i);
                        y      = (int)(y_ratio * j);
                        x_diff = (x_ratio * i) - x;
                        y_diff = (y_ratio * j) - y;
                        index  = y * sourceData.Stride + x;

                        A    = sourceBuffer[index] & 0xff;
                        B    = sourceBuffer[index + 1] & 0xff;
                        C    = sourceBuffer[index + sourceData.Stride] & 0xff;
                        D    = sourceBuffer[index + sourceData.Stride + 1] & 0xff;
                        gray = (int)(
                            A * (1 - x_diff) * (1 - y_diff) + B * (x_diff) * (1 - y_diff) +
                            C * (y_diff) * (1 - x_diff) + D * (x_diff * y_diff)
                            );

                        destinationBuffer[offset++] = (byte)gray;
                        break;
                    }
                    }
                }
            }

            // Copy binary image data to destination bitmap
            Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            ret.UnlockBits(destinationData);
            return(ret);
        }