example ejemplo c# bitmap system.drawing

example - bitmap c# ejemplo



Cómo evitar el mapa de bits de la memoria cuando se trabaja en una imagen muy grande, por ejemplo: 10.000.000 píxeles y más (2)

Actualmente estoy trabajando en un sistema que carga una imagen muy grande, con un ancho mínimo x altura> = 10.000.000 píxeles.

Pero la proporción de la imagen de carga del usuario generalmente no coincide con nuestra proporción de requisitos, por lo que tengo que recortarla a la proporción adecuada, pero cuando uso System.Drawing bitmap para recortarla, siempre tengo la excepción SytemOutOfMemory.

He intentado Bitmap.Clone y Graphic.DrawImage con el RectangleF correcto pero sin suerte.

¿Hay alguna forma de hacer esto sin obtener la excepción de memoria extra o hay alguna alternativa a System.Drawing library para realizar esta tarea fácilmente?

Mi código para cargar la imagen desde el archivo de carga del usuario:

var fileBinary = new byte[stream.Length]; stream.Read(fileBinary, 0, fileBinary.Length); stream.Position = 0; var fileExtension = Path.GetExtension(fileName); using (Image image = Image.FromStream(stream, false, false)) { //validation and check ratio CropImage(image, PORTRAIT_RATIO, fileExtension); }

Y la función CropImage:

//Crop Image from center with predefine ratio private byte[] CropImage(Image sourceImg, float ratio, string fileExtension) var height = sourceImg.Height; var width = sourceImg.Width; var isPortrait = width < height; RectangleF croppingRec = new RectangleF(); float positionX = 0; float positionY = 0; float cropHeight = (float)height; float cropWidth = cropHeight * PORTRAIT_RATIO; positionY = 0; positionX = (width - cropWidth) / 2; if (cropWidth > width) { cropWidth = width; cropHeight = cropWidth * (1 / PORTRAIT_RATIO); positionX = 0; positionY = ((height - cropHeight) / 2); } croppingRec.Width = cropWidth; croppingRec.Height = cropHeight; croppingRec.X = positionX; croppingRec.Y = positionY; Bitmap bmpImage = sourceImg as Bitmap; Bitmap bmpCrop = bmpImage.Clone(croppingRec, bmpImage.PixelFormat); bmpCrop.Save("D:/test" + fileExtension, ImageFormat.Jpeg); ImageConverter converter = new ImageConverter(); return (byte[])converter.ConvertTo(bmpCrop, typeof(byte[])); } }


Intente usar la biblioteca graphicsmagick.net , luego use el método Crop en MagickImage. Todavía debería funcionar bien en asp.net, y maneja archivos de imágenes enormes usando el disco para rascarse.


Podría convertir el mapa de bits a una matriz de bytes. Intenta algo como esto (parece hackie pero no conozco otra manera):

int pixelSize = 3; int bytesCount = imgHeight * imgWidth * pixelSize; byte[] byteArray= new byte[bytesCount]; BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.ReadOnly, bitmap.PixelFormat); Marshal.Copy(bitmapData.Scan0, byteArray, 0, bytesCount);

Cada píxel en esta matriz está representado por 3 bytes (esto depende del tipo de mapa de bits). Así que ya sabes que la longitud de una línea de mapa de bits es 3 * imgWidth. Usando esto, simplemente puede navegar en la matriz de bytes y copiar lo que necesita en una nueva matriz.

Luego, crearía un nuevo mapa de bits con el tamaño final deseado, obtendría los datos del mapa de bits y Marshal. Copie la nueva matriz en eso:

Bitmap newBitmap = new Bitmap(Width, Height); BitmapData newBitmapData = b.LockBits(BoundsRect, ImageLockMode.WriteOnly, newBitmap.PixelFormat); Marshal.Copy(newByteArray, 0, newBitmapData.Scan0, newBytesCount);

Desbloquea los bitmaps al final:

newBitmap.UnlockBits(newBitmapData ); bitmap.UnlockBits(bitmapData);

Espero que esto ayude. Aclamaciones.