2012-07-13 30 views
7

पर बिटमैप को कनवर्ट करना मैं एक छवि को मोनोक्रोम (काला & सफेद, 1 बिट-गहराई) के रूप में सहेजने की कोशिश कर रहा हूं, लेकिन मैं इसे खोने के लिए खो रहा हूं।मोनोक्रोम

मैं एक पीएनजी से शुरू कर रहा हूं और प्रिंटिंग के लिए बिटमैप में परिवर्तित कर रहा हूं (यह एक थर्मल प्रिंटर है और केवल काले रंग का समर्थन करता है - साथ ही अगर मैं उन्हें रंग/ग्रेस्केल के रूप में भेजने की कोशिश करता हूं तो बड़ी छवियों के लिए नरक के रूप में धीमा)।

मेरा कोड अब तक बिटमैप में परिवर्तित करने के लिए सरल है, लेकिन यह मूल रंग गहराई को बनाए रखता है।

Image image = Image.FromFile("C:\\test.png"); 

byte[] bitmapFileData = null; 
int bitsPerPixel = 1; 
int bitmapDataLength; 

using (MemoryStream str = new MemoryStream()) 
{ 
    image.Save(str, ImageFormat.Bmp); 
    bitmapFileData = str.ToArray(); 
} 
+0

http://stackoverflow.com/questions/4669317/how-to-convert-a-bitmap-image-to-black-and-white-in-c – Dmitriy

+0

की [काला करने के लिए छवि परिवर्तित संभव डुप्लिकेट -हाइट या सेपिया सी #] (http://stackoverflow.com/questions/4624998/convert-image-to-black-white-or-sepia-in-c-sharp) – ken2k

+1

दरअसल, ऐसा लगता है कि ये प्रश्न हैं ग्रेस्केल में कनवर्ट करने के बारे में - जबकि ओपी इसे 1 बीपीपी मोनोक्रोम में परिवर्तित करना चाहता है, जिसमें थ्रेसहोल्डिंग/डाइटिंग शामिल है। – Ani

उत्तर

10

यहां कुछ कोड है जो मैंने एक साथ रखा है जो एक पूर्ण रंग (24 बिट/पिक्सेल) छवि लेता है, और इसे 1 बिट/पिक्सेल आउटपुट बिटमैप में परिवर्तित करता है, एक मानक आरजीबी को ग्रेस्केल रूपांतरण में लागू करता है, और फिर फ़्लॉइड-स्टीनबर्ग का उपयोग करता है ग्रेस्केल को 1 बिट/पिक्सेल आउटपुट में कनवर्ट करें।

ध्यान दें कि इसे किसी भी "आदर्श" कार्यान्वयन के रूप में नहीं माना जाना चाहिए, लेकिन यह काम करता है। यदि आप चाहते थे तो कई सुधार किए जा सकते हैं। उदाहरण के लिए, यह पूरे इनपुट छवि को data सरणी में प्रतिलिपि बनाता है, जबकि हमें वास्तव में त्रुटि डेटा जमा करने के लिए केवल दो पंक्तियों को स्मृति ("वर्तमान" और "अगली" पंक्तियां) रखने की आवश्यकता होती है। इसके बावजूद, प्रदर्शन स्वीकार्य लगता है।

public static Bitmap ConvertTo1Bit(Bitmap input) 
{ 
    var masks = new byte[] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 
    var output = new Bitmap(input.Width, input.Height, PixelFormat.Format1bppIndexed); 
    var data = new sbyte[input.Width, input.Height]; 
    var inputData = input.LockBits(new Rectangle(0, 0, input.Width, input.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 
    try 
    { 
     var scanLine = inputData.Scan0; 
     var line = new byte[inputData.Stride]; 
     for (var y = 0; y < inputData.Height; y++, scanLine += inputData.Stride) 
     { 
      Marshal.Copy(scanLine, line, 0, line.Length); 
      for (var x = 0; x < input.Width; x++) 
      { 
       data[x, y] = (sbyte)(64 * (GetGreyLevel(line[x * 3 + 2], line[x * 3 + 1], line[x * 3 + 0]) - 0.5)); 
      } 
     } 
    } 
    finally 
    { 
     input.UnlockBits(inputData); 
    } 
    var outputData = output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); 
    try 
    { 
     var scanLine = outputData.Scan0; 
     for (var y = 0; y < outputData.Height; y++, scanLine += outputData.Stride) 
     { 
      var line = new byte[outputData.Stride]; 
      for (var x = 0; x < input.Width; x++) 
      { 
       var j = data[x, y] > 0; 
       if (j) line[x/8] |= masks[x % 8]; 
       var error = (sbyte)(data[x, y] - (j ? 32 : -32)); 
       if (x < input.Width - 1) data[x + 1, y] += (sbyte)(7 * error/16); 
       if (y < input.Height - 1) 
       { 
        if (x > 0) data[x - 1, y + 1] += (sbyte)(3 * error/16); 
        data[x, y + 1] += (sbyte)(5 * error/16); 
        if (x < input.Width - 1) data[x + 1, y + 1] += (sbyte)(1 * error/16); 
       } 
      } 
      Marshal.Copy(line, 0, scanLine, outputData.Stride); 
     } 
    } 
    finally 
    { 
     output.UnlockBits(outputData); 
    } 
    return output; 
} 

public static double GetGreyLevel(byte r, byte g, byte b) 
{ 
    return (r * 0.299 + g * 0.587 + b * 0.114)/255; 
} 
4

तुम क्या चाहते Floyd-Steinberg या Bayer ordered की तरह एक अच्छा कटौती एल्गोरिथ्म है। आप या तो अपने लिए बिनराइजेशन लागू कर सकते हैं या AForge.NET जैसे लाइब्रेरी का उपयोग कर सकते हैं ताकि यह आपके लिए किया जा सके (छवि प्रसंस्करण नमूने डाउनलोड करें)। आप बिनराइजेशन प्रलेखन here पा सकते हैं।