2011-11-12 10 views
19

लगता है कि मैं बिटमैप (System.Drawing.Bitmap) से सभी बाइट मान प्राप्त करने का प्रयास करता हूं। इसलिए मैं बाइट्स ताला और उन्हें कॉपी:PixelFormat.Format32bppArgb में गलत बाइट ऑर्डर

public static byte[] GetPixels(Bitmap bitmap){ 
    if(bitmap-PixelFormat.Equals(PixelFormat.Format32.bppArgb)){ 
     var argbData = new byte[bitmap.Width*bitmap.Height*4]; 
     var bd = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 
     System.Runtime.InteropServices.Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4); 
     bitmap.UnlockBits(bd); 
    } 
} 

मैं पिक्सल (लाल, हरा, नीला, सफेद) है कि मैं में फ़ोटोशॉप बनाया के साथ एक बहुत ही सरल 2x2 PNG छवि के साथ इस छवि का परीक्षण किया। प्रारूप की वजह से, मैं argbData भीतर निम्न मान की उम्मीद:

255 255 0 0 255 0 255 0 
255 0  0 255 255 255 255 255 

लेकिन मुझे मिल गया:

0  0 255 255  0 255 0 255 
255 0 0 255 255 255 255 255 

लेकिन यह एक BGRA स्वरूप है। क्या कोई जानता है कि बाइट्स क्यों बदलते हैं? वैसे, जब मैं छवि के लिए सीधे छवि का उपयोग करता हूं, जैसा कि नीचे दिखाया गया है, छवि सही ढंग से दिखायी गयी है। तो मेरी गलती क्या है?

<Image Source="D:/tmp/test2.png"/> 

उत्तर

33

पिक्सेल डेटा ARGB, 1 अल्फा के लिए बाइट है , लाल के लिए 1, हरे रंग के लिए 1, नीले रंग के लिए 1। अल्फा सबसे महत्वपूर्ण बाइट है, नीला कम से कम महत्वपूर्ण है। एक छोटी-छोटी मशीन पर, आपके और कई अन्य लोगों की तरह, थोड़ा अंत पहले संग्रहीत होता है ताकि बाइट ऑर्डर बीबी जीजी आरआरए हो। तो 0 0 255 255 नीले = 0, हरे = 0, लाल = 255, अल्फा = 255 के बराबर है। यह लाल है।

यह एंडियन-नेस ऑर्डर विवरण गायब हो जाता है जब आप bd.Scan0 को int * (पॉइंटर-टू-इंटीजर) पर कास्ट करते हैं क्योंकि पूर्णांक को छोटे-एंडियन भी संग्रहीत किया जाता है।

+4

एक्सेलेंट! मैं केवल इतना जोड़ सकता हूं कि आप बाइट ऑर्डर ("एंडियननेस") देख सकते हैं जिसमें डेटा इस कंप्यूटर आर्किटेक्चर में [BitConverter.IsLittleEndian] के माध्यम से संग्रहीत किया जाता है (http://msdn.microsoft.com/en-us/library/system .bitconverter.islittleendian.aspx) फ़ील्ड। – DmitryG

+1

यह 'बिटकॉन्टर.इस्लिटल इंडियन' के बारे में एक अच्छा बिंदु है, लेकिन मुझे लगता है कि एंडियन-नेस के बारे में @ हंसपैसेंट की टिप्पणी वास्तव में मूल्यवान है - यह एक और जगह है जहां एंडियन-नेस ** ** पर विचार नहीं किया जाना चाहिए। [यहां है] (http://commandcenter.blogspot.com.au/2012/04/byte-order-fallacy.html) इस विषय के बारे में एक महान लेख .. – Jonno

2

AFAIK यह तकनीकी रूप से पर COLORREF (जो विंडोज GDI में प्रयोग किया जाता है/GDI + हर जगह) आधारित है और कहा कि स्मृति में RGBA संग्रहीत किया जाता है ... देख http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx

+0

यदि मैं पृष्ठ को समझता हूं, तो इसका मतलब है कि हर बार जब मैं आरजीबी तैयार करता हूं, तो यह वास्तविक बाइटऑर्डर नहीं है। यह हमेशा बीजीआर का मतलब है? या क्या यह संकेत देने वाला एक झंडा है? – 0xBADF00D

+1

@ हिचरेरेक्वा जीडीआई का उपयोग करते समय मैं जो इकट्ठा करता हूं उससे आपको हमेशा बीजीआर/बीजीआरए मिलता है ... – Yahia

0

Bpp32Argb पिक्सेल प्रारूप में। आपको बाइट-बाय-बाइट एक्सेस की आवश्यकता नहीं है।

असुरक्षित संदर्भ में एक इंट 32 सूचक में ट्रुन स्कैन 0।

unsafe 
{ 
    var ptr=(int*)bmData.Scan0; 
} 

आप पहले पिक्सेल के रंग चैनलों तक पहुंचने के लिए नीचे कुछ ऑपरेशन कर सकते हैं।

और बाइट-ऑर्डर की देखभाल करने की आवश्यकता नहीं है।

var a=(ptr[0] & 0xFF000000)>>24; 
var r=(ptr[0] & 0x00FF0000)>>16; 
var g=(ptr[0] & 0x0000FF00)>>8; 
var b=(ptr[0] & 0x000000FF); 

BTW आप Color.ToArgb() आसानी से int लौटे के साथ काम कर सकते हैं।

+0

स्वीकार्य उत्तर पहले से ही इसका उल्लेख करता है, लेकिन दुर्भाग्यवश आप नहीं कर सकते कुछ परिस्थितियों में असुरक्षित कोड का उपयोग करें। उदाहरण के लिए, मैंने कई कंपनियों के लिए काम किया जो असुरक्षित कोड की अनुमति नहीं देते हैं। – 0xBADF00D

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