/// <summary> /// Creates a copy of the given bitmap after cropping white pixels from top and bottom of image. /// Requires a 1bitPerPixel image format, and must be a regular sized fax bitmap (1728 pixels wide). /// after rotation using the supplied intermediate resolution /// and Angle. Positive Angle is Clockwise. The resulting image has the same horizonatal /// and vertical resolution as the given page, but geometry may have changed (height and width). /// </summary> /// <param name="bmp">The Bitmap to rotate</param> /// <param name="intermediateResolution">The intermediate resolution to use.</param> /// <param name="rotationAngle">The angle to rotate the image</param> /// <returns></returns> public static Bitmap CreateCopyCrop(Bitmap bmp) { PageInfo bmpinfo = new PageInfo(bmp); if (bmpinfo.WidthPixels != ImageUtility.FAX_TIF_HOR_PX && bmpinfo.HorizontalResolution != ImageUtility.FAX_TIF_HOR_RES) { throw new Exception("Bitmap is not the correct size for cropping."); } if (bmp.PixelFormat != PixelFormat.Format1bppIndexed) { throw new Exception("Bitmap is not the correct pixel format for cropping."); } // 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); int firstDataRow = BitmapHelper.ScanForFirstNonWhiteRow(sourceBuffer, sourceData.Stride, true, false); int lastDataRow = BitmapHelper.ScanForFirstNonWhiteRow(sourceBuffer, sourceData.Stride, false, true); int totalRows = lastDataRow - firstDataRow + 1; int newHeight = 0; var quality = FaxQuality.Undefined; var paper = PaperSize.Undefined; if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_HI) { if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LTR_HI) { newHeight = ImageUtility.FAX_TIF_VER_PX_LTR_HI; paper = PaperSize.Letter; } else if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LGL_HI) { newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_HI; paper = PaperSize.Legal; } else { newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_HI; paper = PaperSize.Legal; } quality = FaxQuality.Fine; } if (bmp.VerticalResolution == ImageUtility.FAX_TIF_VER_RES_LOW) { if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LTR_LOW) { newHeight = ImageUtility.FAX_TIF_VER_PX_LTR_LOW; paper = PaperSize.Letter; } else if (totalRows <= ImageUtility.FAX_TIF_VER_PX_LGL_LOW) { newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_LOW; paper = PaperSize.Legal; } else { newHeight = ImageUtility.FAX_TIF_VER_PX_LGL_LOW; paper = PaperSize.Legal; } quality = FaxQuality.Normal; } //Make sure the first data row does not go negative. firstDataRow = Math.Max(0, firstDataRow - ((newHeight - totalRows) / 2)); //Make sure last does not extend out of the original document range. lastDataRow = Math.Min(Math.Max(0, bmp.Height - 1), Math.Max(0, firstDataRow + newHeight - 1)); totalRows = lastDataRow - firstDataRow + 1; var startindex = firstDataRow * sourceData.Stride; var length = totalRows * sourceData.Stride; var croppedBitmap = BitmapHelper.CreateBitMap(paper, quality, PixelFormat.Format1bppIndexed); // Lock destination bitmap in memory BitmapData destinationData = croppedBitmap.LockBits(new Rectangle(0, 0, croppedBitmap.Width, croppedBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Copy binary image data to destination bitmap Marshal.Copy(sourceBuffer, startindex, destinationData.Scan0, length); // Unlock destination bitmap croppedBitmap.UnlockBits(destinationData); return(croppedBitmap); }