2015-04-09 9 views
19
ऊपर

वर्तमान में मैं एक प्रणाली है कि एक बहुत बड़ी छवि को लोड पर काम कर रहा हूँ, कम से कम चौड़ाई x अजी> = 10.000.000 साथ पिक्सेल।स्मृति से बाहर बिटमैप से बचने के लिए कैसे जब यानी के लिए बहुत बड़ी छवि पर काम: 10.000.000 पिक्सेल और

लेकिन उपयोगकर्ता की अपलोड छवि का अनुपात आमतौर पर हमारे आवश्यकता अनुपात से मेल नहीं खाता है, इसलिए मुझे इसे उचित अनुपात में फसल करना है, लेकिन सिस्टम का उपयोग करते समय इसे फसल करने के लिए बिटमैप ड्रॉ करना, मुझे हमेशा SytemOutOfMemory अपवाद मिला।

मैं सही RectangleF लेकिन कोई भाग्य के साथ Bitmap.Clone और Graphic.DrawImage कोशिश की है।

वहाँ वैसे भी OutOfMemory अपवाद हो रही बिना यह कर या वहाँ System.Drawing पुस्तकालय के लिए किसी भी विकल्प इस कार्य को आसानी से किया जाना कर रहे हैं है?

उपयोगकर्ता अपलोड फ़ाइल से चित्र करने के लिए मेरा कोड:

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); 
    } 

और 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[])); 
    } 

} 
+0

जांच http://imageresizing.net/ – jle

+4

आप विशेष ध्वज कि (अधिकतम 2GB की अलग एकल सूची संग्रह के लिए) clr से स्मृति प्रतिबंध को हटा के साथ '64bit' एप्लिकेशन के रूप में संकलित करने के लिए कोशिश की थी? – Tigran

+7

10 लाख पिक्सल सामान्य रूप से एक समस्या नहीं है, आधे से एक अरब सैद्धांतिक अधिकतम है, लेकिन एक 32-बिट प्रक्रिया में आपको लगता है कि इससे पहले कि अच्छी तरह से गिर जाते हैं। आमतौर पर लगभग 25 मिलियन यदि आपका प्रोग्राम थोड़ी देर के लिए चल रहा है। आपके कोड में सबसे अधिक संभावना बग निपटान() को कॉल करना भूल रहा है, जब आप बिटमैप क्लास का उपयोग करते हैं तो यह एक रॉक-हार्ड आवश्यकता है और जिस तरह से बहुत से प्रोग्रामर इसके बारे में भूल जाते हैं। जब आप अपना कोड पोस्ट नहीं करते हैं तो कोई भी आपकी बग नहीं देख सकता है। –

उत्तर

0

graphicsmagick.net लाइब्रेरी का उपयोग कर प्रयास करें, तो MagickImage पर फसल पद्धति का उपयोग। यह अभी भी एएसपीनेट के तहत अच्छी तरह से काम करना चाहिए, और स्क्रैच के लिए डिस्क का उपयोग कर विशाल छवि फ़ाइलों को संभालता है।

2

आप एक बाइट सरणी बिटमैप परिवर्तित कर सकते हैं। कुछ इस तरह का प्रयास करें (hackie लग रहा है, लेकिन मैं एक और तरीका है पता नहीं है):

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); 

इस सरणी में प्रत्येक पिक्सेल 3 बाइट्स का प्रतिनिधित्व करती है (इस बिटमैप प्रकार पर निर्भर करता)। तो आप जानते हैं कि बिटमैप लाइन का लंबाई 3 * imgWidth है। इसका उपयोग करके आप बाइट सरणी में बस नेविगेट कर सकते हैं और आपको केवल एक नई सरणी में जो चाहिए उसे कॉपी कर सकते हैं।

फिर आप वांछित अंतिम आकार के साथ एक नया बिटमैप, नई सरणी कि में पैदा करेगा बिटमैप डेटा प्राप्त करें और Marshal.Copy:

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

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

अंत में बिटमैप्स अनलॉक

उम्मीद है कि यह मदद करता है। चीयर्स।

संबंधित मुद्दे