Image को Byte array में बदलने का सबसे तेज़ तरीका


106

मैं दूरस्थ डेस्कटॉप साझाकरण एप्लिकेशन बना रहा हूं जिसमें मैं डेस्कटॉप की एक छवि को कैप्चर करता हूं और इसे कंप्रेस करके रिसीवर को भेजता हूं। छवि को संपीड़ित करने के लिए मुझे इसे बाइट में बदलने की जरूरत है []।

वर्तमान में मैं इसका उपयोग कर रहा हूं:

public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
    MemoryStream ms = new MemoryStream();
    imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
    return  ms.ToArray();
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
     MemoryStream ms = new MemoryStream(byteArrayIn);
     Image returnImage = Image.FromStream(ms);
     return returnImage;
}

लेकिन मुझे यह पसंद नहीं है क्योंकि मुझे इसे एक ImageFormat में सहेजना है और यह संसाधनों (धीमे डाउन) का उपयोग करने के साथ-साथ विभिन्न संपीड़न परिणामों का उत्पादन भी कर सकता है। मैंने मार्शल और चोपसी का उपयोग करने पर पढ़ा है लेकिन मैं इसमें असमर्थ हूं उन्हें समझें।

तो क्या इस लक्ष्य को हासिल करने का कोई और तरीका है?


MemoryStream और Image दोनों में डिस्पोज़ करने का तरीका होता है, सुनिश्चित करें कि आप इन्हें डिस्पोज़ कर रहे हैं क्योंकि यह MemoryLeaks का कारण बन सकता है।
abc123

3
@ abc123: आपको निपटाने की आवश्यकता नहीं है MemoryStream; यह पूरी तरह से प्रबंधित संसाधन है, जब तक कि आप इसे रीमोट करने में उपयोग नहीं कर रहे हैं। इन दोनों मामलों में संसाधन का निपटान करना अनुचित होगा।
जॉन स्कीट

1
@JonSkeet दिलचस्प है, क्या आपने उस पर एक बेंचमार्क किया है? गति को देखने के लिए किस पर .net वस्तु को छोड़ता है? मुझे पता है कि डेटाटेबल के लिए एक समान तर्क है और फिर भी गति में एक ध्यान देने योग्य अंतर है कि गारबेज कोलोरेक्टर एक डिस्पोजल का उपयोग करने पर आवंटित मेमोरी को इकट्ठा करता है।
abc123

@ abc123: मुझे वास्तव में वहाँ होने की उम्मीद नहीं है - धारा का निपटान करने से सरणी को कुछ नहीं होता है, और मेमोरीस्ट्रीम में एक अंतिम रूप नहीं होता है (डेटाटेबल के विपरीत, जो मार्शलहैवेल्यूकम्पेनेंट से विरासत में मिला है)।
जॉन स्कीट

2
पूर्ण स्रोत कोड के साथ कोई अंतिम समाधान?
किवनीत

जवाबों:


39

तो क्या इस लक्ष्य को हासिल करने का कोई और तरीका है?

सं आदेश में एक बाइट सरणी आप के लिए एक छवि बदलने के लिए है एक छवि प्रारूप निर्दिष्ट करने के लिए - आप जब आप एक बाइट सरणी के लिए पाठ परिवर्तित एनकोडिंग निर्दिष्ट करने के लिए है बस के रूप में।

यदि आप संपीड़न कलाकृतियों के बारे में चिंतित हैं, तो दोषरहित प्रारूप चुनें। यदि आप CPU संसाधनों के बारे में चिंतित हैं, तो एक प्रारूप चुनें, जो कंप्रेसिंग को परेशान नहीं करता है - उदाहरण के लिए, केवल कच्चा ARGB पिक्सेल। लेकिन निश्चित रूप से एक बड़ा बाइट सरणी के लिए नेतृत्व करेंगे।

ध्यान दें कि यदि आप एक प्रारूप है जो लेने करता संपीड़न में शामिल हैं, तो बाइट सरणी बाद में संपीड़ित करने में कोई मतलब नहीं है - यह कोई लाभकारी प्रभाव है लगभग तय है।


12
'एक दोषरहित प्रारूप' को चुनने के बजाय, आप imageIn.RawFormatफिर से एन्कोडिंग के बिना कच्ची छवि बाइट्स को सहेजने का प्रयास कर सकते हैं ।
क्रिस एफ कैरोल

52

छवि पैरामीटर का एक रॉफ़ॉर्मैट गुण है जो छवि के फ़ाइल प्रारूप को लौटाता है। आप निम्नलिखित की कोशिश कर सकते हैं:

// extension method
public static byte[] imageToByteArray(this System.Drawing.Image image)
{
    using(var ms = new MemoryStream())
    {
        image.Save(ms, image.RawFormat);
        return ms.ToArray();
    }
}

9
मैं या तो मैमोरीस्ट्रीम के निस्तारण की सलाह दूंगा या इस विधि का उपयोग करके शरीर को लपेट कर () {} स्टेटमेंट
Neil.Allen

@ नील। मैं नया हूँ यहाँ आप कृपया बता सकते हैं क्यों?
खलील खलफ

3
@FirstStep क्योंकि खुद के बाद साफ हो गया :)
सिनास्टेटिक

@ सीनैस्टिक मैं देख रहा हूं। और दिनचर्या यह है कि मैं जिस भी फंक्शन को निष्पादित करना चाहता हूं, एक प्रयोग () {} में करें?
खलील खलफ

2
@ फ़र्स्टस्टेप बिल्कुल नहीं। अधिक सटीक रूप से: यदि आप एक ऐसी वस्तु का उपयोग करते हैं, जिसने आईडीसिसोपयोगी को लागू किया है, तो आपको यह सुनिश्चित करना चाहिए कि जब आप इसके साथ काम कर रहे हों तो डिस्पोज () को कॉल करें ताकि यह किसी भी संसाधन को साफ कर दे जिसे उसने बांध दिया है। उस कथन के दायरे से बाहर जाने पर () {} स्टेटमेंट केवल आपके लिए इसे कॉल करता है। तो आप कर सकते हैं myObject.Dispose()या using(myObject){}- दोनों एक ही काम करते हैं, लेकिन मूल रूप से बयान का उपयोग एक गुंजाइश बनाता है जो आपके लिए साफ हो जाएगा।
सिनास्टैटिक

14

मुझे यकीन नहीं है कि अगर आप जॉन स्कीट द्वारा बताए गए कारणों के लिए कोई बड़ा लाभ प्राप्त करने जा रहे हैं। हालाँकि, आप TypeConvert.ConvertTo विधि को आज़मा सकते हैं और देख सकते हैं कि यह आपके वर्तमान तरीके का उपयोग करने की तुलना कैसे करता है।

ImageConverter converter = new ImageConverter();
byte[] imgArray = (byte[])converter.ConvertTo(imageIn, typeof(byte[]));

'System.Byte' टाइप करने के लिए 'System.Byte [] टाइप का ऑब्जेक्ट डालने में असमर्थ।
user123

14
public static byte[] ReadImageFile(string imageLocation)
    {
        byte[] imageData = null;
        FileInfo fileInfo = new FileInfo(imageLocation);
        long imageFileLength = fileInfo.Length;
        FileStream fs = new FileStream(imageLocation, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);
        imageData = br.ReadBytes((int)imageFileLength);
        return imageData;
    }

5
आपका स्वागत है stackoverflow.com पर, क्या आप यह बताकर थोड़ा विस्तार जोड़ सकते हैं कि ऊपर का कोड सैंपल क्यों मदद करता है। यह अन्य SO उपयोगकर्ताओं के लिए है जो इसे पूरी तरह से नहीं समझ सकते हैं ... stackoverflow.com/help/how-to-answer
मैक

यह बाइट्स के लिए फ़ाइलों के लिए है, लेकिन ओपी बाइट्स में परिवर्तित एक ड्राइंग ऑब्जेक्ट चाहता था। आरेखण ऑब्जेक्ट्स डेटाबेस में संग्रहीत किए जा सकते हैं, जरूरी नहीं कि फाइल सिस्टम, बाइट्स की एक सरणी के रूप में, और इसलिए आगे और पीछे बदलना होगा ... लेकिन बाइट्स में परिवर्तित होने वाली फाइलस्ट्रीम में फ़ाइलों के रूप में नहीं - जब तक कि शायद, दौरान। प्रारंभिक अपलोड
vapcguy

इससे मुझे मदद मिली क्योंकि मैं फ़ाइलों के साथ ऐसा करना चाह रहा था। इसके संबंधित के रूप में अच्छा है।
जस्टिन

5
public static class HelperExtensions
{
    //Convert Image to byte[] array:
    public static byte[] ToByteArray(this Image imageIn)
    {
        var ms = new MemoryStream();
        imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        return ms.ToArray();
    }

    //Convert byte[] array to Image:
    public static Image ToImage(this byte[] byteArrayIn)
    {
        var ms = new MemoryStream(byteArrayIn);
        var returnImage = Image.FromStream(ms);
        return returnImage;
    }
}

2

सबसे तेज़ तरीका जो मैं जान सकता था वह यह है:

var myArray = (byte[]) new ImageConverter().ConvertTo(InputImg, typeof(byte[]));

उपयोगी होने की उम्मीद है


इसके साथ सावधान रहें, खासकर अगर WPF का उपयोग करते हुए जहां आपके पास System.Windows.Controls.Imageऑब्जेक्ट होंगे। यदि आप उन बाइट्स में से एक को बदलना चाहते हैं, और आप इसे इस पंक्ति में पास करते हैं InputImg, तो यह काम नहीं करेगा। यह एक System.Drawing.Imageवस्तु की अपेक्षा करता है।
vapcguy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.