2012-02-07 31 views
56

मैं एक बाइट सरणी को एक छवि में परिवर्तित करना चाहता हूं।बाइट ऐरे छवि रूपांतरण

जहाँ मैं बाइट सरणी मिल से मेरी डेटाबेस कोड यह है:

public void Get_Finger_print() 
{ 
    try 
    { 
     using (SqlConnection thisConnection = new SqlConnection(@"Data Source=" + System.Environment.MachineName + "\\SQLEXPRESS;Initial Catalog=Image_Scanning;Integrated Security=SSPI ")) 
     { 
      thisConnection.Open(); 
      string query = "select pic from Image_tbl";// where Name='" + name + "'"; 
      SqlCommand cmd = new SqlCommand(query, thisConnection); 
      byte[] image =(byte[]) cmd.ExecuteScalar(); 
      Image newImage = byteArrayToImage(image); 
      Picture.Image = newImage; 
      //return image; 
     } 
    } 
    catch (Exception) { } 
    //return null; 
} 

मेरे रूपांतरण कोड:

public Image byteArrayToImage(byte[] byteArrayIn) 
{ 
    try 
    { 
     MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
     ms.Write(byteArrayIn, 0, byteArrayIn.Length); 
     returnImage = Image.FromStream(ms,true);//Exception occurs here 
    } 
    catch { } 
    return returnImage; 
} 

जब मैं एक टिप्पणी के साथ सीमा तक पहुंच जाती है, तो निम्न अपवाद तब होता है: Parameter is not valid.

इस अपवाद को उत्पन्न करने वाले किसी भी चीज़ को मैं कैसे ठीक कर सकता हूं?

+0

क्या आपने जांच की है कि आपकी क्वेरी में छवि बाइट मान्य हैं? आप सत्यापित करने के लिए एक फ़ाइल.WriteAllBytes ("myimage.jpg", byteArrayIn) कर सकते हैं। – Holstebroe

उत्तर

4

कोशिश (अद्यतन)

MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
ms.Position = 0; // this is important 
returnImage = Image.FromStream(ms,true); 
+0

धन्यवाद लेकिन इस कोड से समस्या हल नहीं की गई –

+2

यह बाइट सरणी को उसी बाइट सरणी के साथ प्रारंभ करने के बाद मेमोरी स्ट्रीम में लिखने के लिए बहुत कम समझ में आता है। असल में मुझे यकीन नहीं है कि मेमोरीस्ट्रीम कन्स्ट्रक्टर में निर्दिष्ट लंबाई से परे लेखन की अनुमति देता है। – Holstebroe

+0

@TanzeelurRahman मेरा संपादित उत्तर देखें ... – Yahia

70

आप दो बार अपनी स्मृति धारा लिए लिख रहे हैं, यह भी आप उपयोग के बाद धारा निपटान नहीं कर रहे हैं। आप एम्बेडेड रंग सुधार लागू करने के लिए छवि डिकोडर से भी पूछ रहे हैं।

ऐसा करें:

using (var ms = new MemoryStream(byteArrayIn)) 
{ 
    return Image.FromStream(ms); 
} 
+0

आप प्रारंभिकरण के बाद भी स्मृति स्ट्रीम को गैर-लिखने योग्य बना सकते हैं: नया मेमोरीस्ट्रीम (बाइटएर्रेइन, झूठा) – Holstebroe

+0

कोई भी कोड मेरी समस्या हल नहीं किया गया है –

+19

यह छवि के लिए एमएसडीएन में एक विनिर्देश का उल्लंघन करता है ।FromStream(), जहां यह कहता है "आपको छवि के जीवनकाल के लिए स्ट्रीम को खुले रखना चाहिए।" यह भी देखें http://stackoverflow.com/questions/3290060/getting-an-image-object-from-a-byte-array – RenniePet

2

यह Holstebroe के जवाब से प्रेरित है, के साथ साथ यहां की टिप्पणियां: Getting an Image object from a byte array

Bitmap newBitmap; 
using (MemoryStream memoryStream = new MemoryStream(byteArrayIn)) 
    using (Image newImage = Image.FromStream(memoryStream)) 
     newBitmap = new Bitmap(newImage); 
return newBitmap; 
55

शायद मैं कुछ याद कर रहा हूँ, लेकिन मेरे लिए यह एक लाइनर ठीक काम करता है एक बाइट सरणी के साथ जिसमें एक जेपीईजी फ़ाइल की एक छवि होती है।

Image x = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray)); 

संपादित करें:

इस उत्तर के एक अद्यतन संस्करण के लिए यहाँ देखें: How to convert image in byte array

+0

ग्रेट ... सहेजे गए समय – PawanS

+0

एएएएच धन्यवाद, अंत में एक अच्छा जवाब। मेमोरी स्ट्रीम के साथ इतने सारे जवाब क्यों हैं, इससे मुझे बहुत समस्या आती है। आपका बहुत बहुत धन्यवाद ! – Julian50

+0

अच्छा जवाब! इसका उपयोग एक अलग समारोह में किया जा सकता है जबकि मेमोरीस्ट्रीम का उपयोग करने वाले अन्य सभी प्रस्ताव नहीं हो सकते हैं (स्ट्रीम छवि के जीवनकाल के लिए खुला रखा जाना चाहिए) –

0

समय जब ऐसा होता है यह एसक्यूएल कॉलम में बुरा डेटा है के अधिकांश। यह एक छवि स्तंभ में डालने के लिए उचित तरीका है:

INSERT INTO [TableX] (ImgColumn) VALUES (
(SELECT * FROM OPENROWSET(BULK N'C:\....\Picture 010.png', SINGLE_BLOB) as tempimg)) 

अधिकांश लोगों को यह कर गलत तरीके से इस तरह से:

INSERT INTO [TableX] (ImgColumn) VALUES ('C:\....\Picture 010.png')) 
0

हाय नीचे दिए गए लिंक की कोशिश मुझे भी एक ही मुद्दा मिल गया और मैं हल मिल गया के लिए नीचे दिए गए लिंक की कोशिश कहीं भी होगी यू enter link description here

2

आप चर के किसी भी प्रकार के रूप में :) returnImage घोषणा नहीं की मदद करता है

यह मदद करनी चाहिए:

public Image byteArrayToImage(byte[] byteArrayIn) 
{ 
    try 
    { 
     MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
     ms.Write(byteArrayIn, 0, byteArrayIn.Length); 
     Image returnImage = Image.FromStream(ms,true); 
    } 
    catch { } 
    return returnImage; 
} 
+1

कोड को एक विचार के रूप में उपयोगी बनाने के लिए इतना आसान है, लेकिन निश्चित रूप से लिखित के रूप में काम नहीं करेगा। वापसी छवि को कोशिश/पकड़ अनुभाग के बाहर घोषित किया जाना है। इसके अलावा वापसी 'इमेज' में तत्काल होना चाहिए - मैं एक पिक्सेल बिटमैप बनाता हूं: var image = new बिटमैप (1, 1); मेमोरीस्ट्रीम स्ट्रीम = नया मेमोरीस्ट्रीम(); छवि। सहेजें (स्ट्रीम, ImageFormat.Jpeg); स्ट्रीम। स्थिति = 0; – Reid

4

सभी प्रस्तुत उत्तरों का मानना ​​है कि बाइट सरणी में एक ज्ञात फ़ाइल प्रारूप प्रतिनिधित्व में डेटा होता है, जैसे: gif, png या jpg। लेकिन मुझे हाल ही में byte[] एस को बदलने की कोशिश करने में समस्या आई थी, जिसमें रैखिक बीजीआरए जानकारी शामिल है, कुशलता से Image ऑब्जेक्ट्स में। निम्नलिखित कोड Bitmap ऑब्जेक्ट का उपयोग करके हल करता है।

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 
public static class Extensions 
{ 
    public static Image ImageFromRawBgraArray(
     this byte[] arr, int width, int height) 
    { 
     var output = new Bitmap(width, height); 
     var rect = new Rectangle(0, 0, width, height); 
     var bmpData = output.LockBits(rect, 
      ImageLockMode.ReadWrite, output.PixelFormat); 
     var ptr = bmpData.Scan0; 
     Marshal.Copy(arr, 0, ptr, arr.Length); 
     output.UnlockBits(bmpData); 
     return output; 
    } 
} 

यह this site पर पोस्ट किए गए समाधान की थोड़ी भिन्नता है।

+0

एक संदर्भ के रूप में एमएसडीएन: बिटमैप (इंट 32, इंट 32): "यह कन्स्ट्रक्टर Format32bppArgb के पिक्सेलफॉर्मैट गणना मूल्य के साथ बिटमैप बनाता है।", जिसका अर्थ है बाइट [0] नीला, बाइट [1] हरा है, बाइट [2] है लाल, बाइट [3] अल्फा है, बाइट [4] नीला है, और इसी तरह। – brk

6
public Image byteArrayToImage(byte[] bytesArr) 
{ 
    MemoryStream memstr = new MemoryStream(bytesArr); 
    Image img = Image.FromStream(memstr); 
    return img; 
} 
+0

हालांकि यह सामान्य रूप से एक अच्छा विचार नहीं है, मैंने मेमोरी स्ट्रीम से पहले एक जीसी। कोलेक्ट() डाल दिया है। मैं स्मृति से बाहर था जब मैंने पूरी तरह से बड़ी ग्राफिक फ़ाइलों को स्मृति में जोड़ दिया और फिर उन्हें देखने के दौरान छवियों में बदल दिया। – Kayot

6

मुझे लगता है कि @ isaias-b द्वारा प्रदान किए गए समाधान में एक बग है।

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

घुमाव पिक्सल (एक स्कैन लाइन) की एक पंक्ति की चौड़ाई है, जो चार-बाइट सीमा तक गोल है।

फिक्स्ड कोड:

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 

public static class ImageExtensions 
{ 
    public static Image ImageFromRawBgraArray(this byte[] arr, int width, int height, PixelFormat pixelFormat) 
    { 
     var output = new Bitmap(width, height, pixelFormat); 
     var rect = new Rectangle(0, 0, width, height); 
     var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat); 

     // Row-by-row copy 
     var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat)/8; 
     var ptr = bmpData.Scan0; 
     for (var i = 0; i < height; i++) 
     { 
      Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength); 
      ptr += bmpData.Stride; 
     } 

     output.UnlockBits(bmpData); 
     return output; 
    } 
} 

इसे समझने के लिए क्या यह हो सकता है, के PixelFormat.Format24bppRgb ढाल छवि 101x101 उत्पन्न करते हैं: हम पूरे सरणी कॉपी जाएगा

var width = 101; 
var height = 101; 
var gradient = new byte[width * height * 3 /* bytes per pixel */]; 
for (int i = 0, pixel = 0; i < gradient.Length; i++, pixel = i/3) 
{ 
    var x = pixel % height; 
    var y = (pixel - x)/width; 
    gradient[i] = (byte)((x/(double)(width - 1) + y/(double)(height - 1))/2d * 255); 
} 

उठाई पता करने के लिए के रूप में है bmpData.Scan0 द्वारा, हमें निम्नलिखित छवि मिल जाएगी। छवि स्थानांतरित हो रही है क्योंकि छवि का हिस्सा पैडिंग बाइट्स पर लिखा गया था, जिसे अनदेखा किया गया था। इसके अलावा यही वजह है कि अंतिम पंक्ति अधूरा है:

stride ignored

लेकिन अगर हम bmpData.Stride मूल्य द्वारा पंक्ति-दर-पंक्ति गंतव्य सूचक स्थानांतरण कॉपी करेंगे, वैध imaged उत्पन्न हो जाएगा:

stride taken into account

स्ट्रिड भी ऋणात्मक हो सकता है:

यदि स्ट्राइड सकारात्मक है, तो बिटमैप शीर्ष-डाउन है। यदि घुमाव नकारात्मक है, तो बिटमैप नीचे-नीचे है।

लेकिन मैंने ऐसी छवियों के साथ काम नहीं किया और यह मेरे नोट से परे है।

संबंधित जवाब: C# - RGB Buffer from Bitmap different from C++

-2

मैंने पाया यह लोग Convert array to image

 private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      string hasil = "D:\\coba1000.jpg"; 
      System.IO.File.WriteAllBytes(@hasil, bytestosend); 


      pictureBox1.ImageLocation = @hasil; 
     } 
     catch { } 
    } 
0

सरल दृष्टिकोण के रूप में नीचे है, तो आप चाल, करने के लिए छवि के FromStream विधि का उपयोग कर सकते हैं बस प्रणाली का उपयोग करने के लिए याद ।चि त्र का री;

// using image object not file 
public byte[] imageToByteArray(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; 
}