วิธีการแปลงรูปภาพเป็นไบต์อาร์เรย์


127

ใครช่วยแนะนำวิธีแปลงภาพเป็นไบต์อาร์เรย์และในทางกลับกันได้ไหม

ฉันกำลังพัฒนาแอปพลิเคชัน WPF และใช้โปรแกรมอ่านสตรีม

คำตอบ:


176

โค้ดตัวอย่างเพื่อเปลี่ยนรูปภาพเป็นอาร์เรย์ไบต์

public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
   using (var ms = new MemoryStream())
   {
      imageIn.Save(ms,imageIn.RawFormat);
      return  ms.ToArray();
   }
}

C # Image ไปยัง Byte Array และ Byte Array to Image Converter Class


12
แทนที่จะSystem.Drawing.Imaging.ImageFormat.Gifใช้imageIn.RawFormat
S. Serpooshan

1
สิ่งนี้ดูเหมือนจะไม่สามารถทำซ้ำได้หรืออย่างน้อยหลังจากการแปลงสองสามครั้งข้อผิดพลาด GDI + แปลก ๆ ก็เริ่มเกิดขึ้น ImageConverterวิธีการแก้ปัญหาด้านล่างนี้ดูเหมือนว่าจะหลีกเลี่ยงข้อผิดพลาดเหล่านี้
Dave Cousineau

อาจจะดีกว่าถ้าใช้ png ตอนนี้วันนี้
Nyerguds

สังเกตด้านบน: นี้อาจมีข้อมูล meta เพิ่มเติมที่คุณไม่ต้องการที่จะมี ;-) เพื่อกำจัดของเมตาดาต้าที่คุณอาจต้องการที่จะสร้างบิตแมปใหม่และผ่านภาพ(new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);มันเหมือน
Markus Safar

56

สำหรับการแปลงออบเจ็กต์รูปภาพbyte[]คุณสามารถทำได้ดังนี้:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}

4
คำตอบที่สมบูรณ์แบบ! .... ไม่จำเป็นต้องกำหนด "นามสกุลไฟล์ภาพ" สิ่งที่ฉันกำลังมองหา
Bravo

1
สังเกตด้านบน: นี้อาจมีข้อมูล meta เพิ่มเติมที่คุณไม่ต้องการที่จะมี ;-) เพื่อกำจัดของเมตาดาต้าที่คุณอาจต้องการที่จะสร้างบิตแมปใหม่และผ่านภาพ.ConvertTo(new Bitmap(x), typeof(byte[]));มันเหมือน
Markus Safar

1
สำหรับฉัน Visual Studio ไม่รู้จักประเภท ImageConverter มีคำสั่งนำเข้าที่จำเป็นสำหรับการใช้งานนี้หรือไม่?
technoman23

32

อีกวิธีหนึ่งในการรับอาร์เรย์ไบต์จากเส้นทางรูปภาพคือ

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));

คำถามของพวกเขาถูกแท็ก WPF (ดังนั้นจึงไม่มีเหตุผลที่จะคิดว่ามันทำงานในเซิร์ฟเวอร์และรวม MapPath ไว้ด้วย) และแสดงว่าพวกเขามีอิมเมจอยู่แล้ว (ไม่มีเหตุผลที่จะอ่านจากดิสก์ไม่ได้คิดว่ามันอยู่ในดิสก์ที่จะเริ่มต้นด้วย) ฉันขอโทษ แต่คำตอบของคุณดูเหมือนไม่เกี่ยวข้องกับคำถามอย่างสิ้นเชิง
Ronan Thibaudau

19

นี่คือสิ่งที่ฉันกำลังใช้อยู่ เทคนิคอื่น ๆ บางอย่างที่ฉันได้ลองใช้แล้วไม่เหมาะสมที่สุดเนื่องจากเปลี่ยนความลึกของพิกเซล (24 บิตเทียบกับ 32 บิต) หรือไม่สนใจความละเอียดของภาพ (dpi)

  // ImageConverter object used to convert byte arrays containing JPEG or PNG file images into 
  //  Bitmap objects. This is static and only gets instantiated once.
  private static readonly ImageConverter _imageConverter = new ImageConverter();

รูปภาพไปยังอาร์เรย์ไบต์:

  /// <summary>
  /// Method to "convert" an Image object into a byte array, formatted in PNG file format, which 
  /// provides lossless compression. This can be used together with the GetImageFromByteArray() 
  /// method to provide a kind of serialization / deserialization. 
  /// </summary>
  /// <param name="theImage">Image object, must be convertable to PNG format</param>
  /// <returns>byte array image of a PNG file containing the image</returns>
  public static byte[] CopyImageToByteArray(Image theImage)
  {
     using (MemoryStream memoryStream = new MemoryStream())
     {
        theImage.Save(memoryStream, ImageFormat.Png);
        return memoryStream.ToArray();
     }
  }

อาร์เรย์ไบต์ไปยังรูปภาพ:

  /// <summary>
  /// Method that uses the ImageConverter object in .Net Framework to convert a byte array, 
  /// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be 
  /// used as an Image object.
  /// </summary>
  /// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
  /// <returns>Bitmap object if it works, else exception is thrown</returns>
  public static Bitmap GetImageFromByteArray(byte[] byteArray)
  {
     Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);

     if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
                        bm.VerticalResolution != (int)bm.VerticalResolution))
     {
        // Correct a strange glitch that has been observed in the test program when converting 
        //  from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts" 
        //  slightly away from the nominal integer value
        bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), 
                         (int)(bm.VerticalResolution + 0.5f));
     }

     return bm;
  }

แก้ไข: ในการรับภาพจากไฟล์ jpg หรือ png คุณควรอ่านไฟล์ในอาร์เรย์ไบต์โดยใช้ File.ReadAllBytes ():

 Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));

วิธีนี้หลีกเลี่ยงปัญหาที่เกี่ยวข้องกับ Bitmap ที่ต้องการให้สตรีมต้นทางเปิดอยู่และวิธีแก้ไขปัญหาบางประการที่แนะนำสำหรับปัญหานั้นซึ่งส่งผลให้ไฟล์ต้นฉบับถูกล็อก


ในระหว่างการทดสอบสิ่งนี้ฉันจะใช้บิตแมปที่เป็นผลลัพธ์และเปลี่ยนกลับเป็นอาร์เรย์ไบต์โดยใช้: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } ซึ่งจะส่งผลให้อาร์เรย์ 2 ขนาดแตกต่างกันเป็นระยะ ๆ โดยปกติสิ่งนี้จะเกิดขึ้นหลังจากการทำซ้ำประมาณ 100 ครั้ง แต่เมื่อฉันได้รับบิตแมปโดยใช้new Bitmap(SourceFileName);แล้วเรียกใช้ผ่านรหัสนั้นมันก็ใช้ได้ดี
ดอน

@ ดอน: ไม่มีไอเดียดีๆเลยจริงๆ สอดคล้องกันหรือไม่ที่รูปภาพไม่ให้ผลลัพธ์เดียวกันกับอินพุต คุณได้ลองตรวจสอบผลลัพธ์เมื่อไม่เป็นไปตามที่คาดไว้เพื่อดูว่าเหตุใดจึงแตกต่างกัน หรืออาจจะไม่สำคัญจริงๆและเราสามารถยอมรับว่า "สิ่งต่างๆเกิดขึ้น"
RenniePet

มันเกิดขึ้นอย่างต่อเนื่อง ไม่เคยพบสาเหตุแม้ว่า ฉันรู้สึกว่ามันน่าจะมีอะไรเกี่ยวข้องกับขอบเขต 4K ไบต์ในการจัดสรรหน่วยความจำ แต่นั่นอาจผิดพลาดได้ง่ายๆ ฉันเปลี่ยนไปใช้ MemoryStream กับ BinaryFormatter และฉันก็สามารถที่จะมีความสอดคล้องกันอย่างมากจากการทดสอบด้วยภาพทดสอบที่แตกต่างกันกว่า 250 รูปในรูปแบบและขนาดที่แตกต่างกันซึ่งวนซ้ำมากกว่า 1,000 ครั้งเพื่อการตรวจสอบ ขอบคุณสำหรับการตอบกลับ.
ดอน

17

ลองสิ่งนี้:

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

imageToByteArray (System.Drawing.Image imageIn) imageIn คือเส้นทางภาพหรือสิ่งอื่นใดที่เราสามารถส่งผ่านภาพในสิ่งนี้
Shashank

นี่คือสิ่งที่ฉันทำได้ทุกเวลาที่ต้องการแปลงรูปภาพเป็นอาร์เรย์ไบต์หรือย้อนกลับ
Alex Essilfie

คุณลืมปิด memorystream ... btw นี้คัดลอกมาจาก: link
Qwerty01

1
@ Qwerty01 การโทร Dispose จะไม่ล้างหน่วยความจำที่ใช้MemoryStreamเร็วกว่าอย่างน้อยก็ในการใช้งานปัจจุบัน ในความเป็นจริงหากคุณปิดคุณจะไม่สามารถใช้งานได้ในImageภายหลังคุณจะได้รับข้อผิดพลาด GDI
แสบอามินี

14

คุณสามารถใช้File.ReadAllBytes()วิธีการอ่านไฟล์ใด ๆ ในไบต์อาร์เรย์ ในการเขียนไบต์อาร์เรย์ลงในไฟล์เพียงใช้File.WriteAllBytes()วิธีการ

หวังว่านี่จะช่วยได้

คุณสามารถค้นหาข้อมูลเพิ่มเติมและตัวอย่างรหัสที่นี่


หมายเหตุด้านข้าง: อาจมีข้อมูลเมตาเพิ่มเติมที่คุณไม่ต้องการมี ;-)
Markus Safar

1
อาจจะ. ฉันเขียนคำตอบนี้เมื่อ 10 ปีที่แล้วตอนนั้นฉันสดชื่นขึ้น / noob
Shekhar

5

คุณต้องการเฉพาะพิกเซลหรือทั้งภาพ (รวมถึงส่วนหัว) เป็นอาร์เรย์ไบต์หรือไม่?

สำหรับพิกเซล: ใช้CopyPixelsวิธีการบน Bitmap สิ่งที่ต้องการ:

var bitmap = new BitmapImage(uri);

//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary and whether the image is 32 bit, 16 bit etc.

bitmap.CopyPixels(..size, pixels, fullStride, 0); 

3

รหัส:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);

1
ใช้งานได้เฉพาะเมื่อเขากำลังอ่านไฟล์ (และถึงแม้เขาจะได้รับไบต์ที่จัดรูปแบบ / บีบอัดไม่ใช่ไฟล์ดิบเว้นแต่จะเป็น BMP)
BradleyDotNET

3

หากคุณไม่อ้างอิง imageBytes เพื่อนำไบต์ในสตรีมเมธอดจะไม่คืนค่าอะไรเลย ตรวจสอบให้แน่ใจว่าคุณอ้างอิง imageBytes = m ToArray ();

    public static byte[] SerializeImage() {
        MemoryStream m;
        string PicPath = pathToImage";

        byte[] imageBytes;
        using (Image image = Image.FromFile(PicPath)) {

            using ( m = new MemoryStream()) {

                image.Save(m, image.RawFormat);
                imageBytes = new byte[m.Length];
               //Very Important    
               imageBytes = m.ToArray();

            }//end using
        }//end using

        return imageBytes;
    }//SerializeImage

[NB] หากคุณยังไม่เห็นภาพในเบราว์เซอร์ฉันได้เขียนขั้นตอนการแก้ปัญหาโดยละเอียด

แก้ไข! -iis ไม่ให้บริการ-CSS, -images และจาวาสคริปต์


1

นี่คือรหัสสำหรับการแปลงรูปภาพทุกประเภท (เช่น PNG, JPG, JPEG) เป็นไบต์อาร์เรย์

   public static byte[] imageConversion(string imageName){            


        //Initialize a file stream to read the image file
        FileStream fs = new FileStream(imageName, FileMode.Open, FileAccess.Read);

        //Initialize a byte array with size of stream
        byte[] imgByteArr = new byte[fs.Length];

        //Read data from the file stream and put into the byte array
        fs.Read(imgByteArr, 0, Convert.ToInt32(fs.Length));

        //Close a file stream
        fs.Close();

        return imageByteArr
    }

หมายเหตุด้านข้าง: อาจมีข้อมูลเมตาเพิ่มเติมที่คุณไม่ต้องการมี ;-)
Markus Safar

0

ในการแปลงภาพเป็นไบต์อาร์เรย์รหัสให้ด้านล่าง

public byte[] ImageToByteArray(System.Drawing.Image images)
{
   using (var _memorystream = new MemoryStream())
   {
      images.Save(_memorystream ,images.RawFormat);
      return  _memorystream .ToArray();
   }
}

ในการแปลงอาร์เรย์ Byte เป็น Image รหัสจะได้รับด้านล่างรหัสนี้จัดการA Generic error occurred in GDI+ใน Image Save

public void SaveImage(string base64String, string filepath)
{
    // image convert to base64string is base64String 
    //File path is which path to save the image.
    var bytess = Convert.FromBase64String(base64String);
    using (var imageFile = new FileStream(filepath, FileMode.Create))
    {
        imageFile.Write(bytess, 0, bytess.Length);
        imageFile.Flush();
    }
}

-2

รหัสนี้ดึงข้อมูล 100 แถวแรกจากตารางใน SQLSERVER 2012 และบันทึกรูปภาพต่อแถวเป็นไฟล์บนโลคัลดิสก์

 public void SavePicture()
    {
        SqlConnection con = new SqlConnection("Data Source=localhost;Integrated security=true;database=databasename");
        SqlDataAdapter da = new SqlDataAdapter("select top 100 [Name] ,[Picture] From tablename", con);
        SqlCommandBuilder MyCB = new SqlCommandBuilder(da);
        DataSet ds = new DataSet("tablename");
        byte[] MyData = new byte[0];
        da.Fill(ds, "tablename");
        DataTable table = ds.Tables["tablename"];
           for (int i = 0; i < table.Rows.Count;i++ )               
               {
                DataRow myRow;
                myRow = ds.Tables["tablename"].Rows[i];
                MyData = (byte[])myRow["Picture"];
                int ArraySize = new int();
                ArraySize = MyData.GetUpperBound(0);
                FileStream fs = new FileStream(@"C:\NewFolder\" + myRow["Name"].ToString() + ".jpg", FileMode.OpenOrCreate, FileAccess.Write);
                fs.Write(MyData, 0, ArraySize);
                fs.Close();
               }

    }

โปรดทราบ: ไดเรกทอรีที่มีชื่อNewFolderควรมีอยู่ใน C: \


3
คุณตอบคำถามผิด ... ดีฉันหวังว่า ^ _ ^
JiBéDoublevé
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.