চিত্র রূপান্তর থেকে বাইট অ্যারে


104

আমি একটি বাইট অ্যারে একটি ছবিতে রূপান্তর করতে চাই।

এটি আমার ডাটাবেস কোডটি থেকে আমি বাইট অ্যারেটি পাই:

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.

এই ব্যতিক্রম ঘটছে যা কিছু আমি কীভাবে ঠিক করতে পারি?


আপনি কি অনুসন্ধান করেছেন যে আপনার প্রশ্নের ইমেজ বাইটগুলি বৈধ? আপনি যাচাই করতে একটি ফাইল.ওরাইটআলবাইটস ("myimage.jpg", বাইটআরআইআইএন) করতে পারেন।
হলস্টেব্রো

উত্তর:


112

আপনি আপনার স্মৃতি প্রবাহে দু'বার লিখেছেন, আপনি ব্যবহারের পরেও স্ট্রিমটি নিষ্পত্তি করছেন না। আপনি চিত্রের ডিকোডারকে এমবেডড রঙ সংশোধন প্রয়োগ করতে বলছেন।

পরিবর্তে এটি চেষ্টা করুন:

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

নতুন MemoryStream (byteArrayIn, মিথ্যা): আপনি স্পষ্টভাবে আরম্ভের পরে মেমরির প্রবাহ অ লিখনযোগ্য করতে পারে
Holstebroe

28
এটি চিত্রের জন্য এমএসডিএন-তে একটি স্পেসিফিকেশন লঙ্ঘন করে romফ্রিমস্ট্রিম () থেকে যেখানে বলা হয়েছে "আপনাকে অবশ্যই চিত্রের আজীবন স্রোতটি উন্মুক্ত রাখতে হবে।" আরও দেখুন stackoverflow.com/questions/3290060/...
RenniePet

82

হয়তো আমি কিছু মিস করছি, তবে আমার জন্য এই ওয়ান-লাইনার একটি বাইট অ্যারেতে দুর্দান্ত কাজ করে যাতে একটি জেপিজি ফাইলের একটি চিত্র থাকে।

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

সম্পাদনা:

এই উত্তরের একটি আপডেট সংস্করণের জন্য এখানে দেখুন: বাইট অ্যারেতে কীভাবে চিত্র রূপান্তর করবেন


এএএএহ ধন্যবাদ, শেষ পর্যন্ত একটি ভাল উত্তর। মেমরি স্ট্রিমের সাথে এত উত্তর কেন, এটি আমাকে এত সমস্যার সৃষ্টি করে। অনেক ধন্যবাদ !
জুলিয়ান 50

ভাল উত্তর! এটি আলাদা ফাংশনে ব্যবহার করা যেতে পারে অন্যদিকে
মেমোরিস্ট্রিম

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

এটি সাধারণত কোনও ভাল ধারণা না হলেও, আমি মেমরি স্ট্রিমের আগে একটি জিসি.কোলেক্ট () রেখেছি। আমি যখন স্মৃতিতে বাইটারারি হিসাবে পুরো বড় গ্রাফিক ফাইলগুলি পূর্বে লোড করেছি এবং সেগুলি দেখার সময় তাদের চিত্রগুলিতে পরিণত করেছি তখন আমি মেমরির বাইরে চলে যাচ্ছিলাম।
কায়োট

10

আমি লক্ষ করতে চাই যে @ ইসাইয়াস-বি দ্বারা প্রদত্ত সমাধানে একটি বাগ রয়েছে।

সমাধানটি 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নীচের চিত্রটি পেয়ে যাব। চিত্রের স্থানান্তর কারণ চিত্রের কিছু অংশ প্যাডিং বাইটে লেখা হয়েছিল, তা উপেক্ষা করা হয়েছিল। এছাড়াও এ কারণেই শেষ সারিটি অসম্পূর্ণ:

অগ্রাহ্য উপেক্ষা করা হয়েছে

তবে আমরা যদি bmpData.Strideমান অনুসারে সারি-সারি সরিয়ে গন্তব্য পয়েন্টারটি অনুলিপি করি তবে বৈধ চিত্রযুক্ত উত্পন্ন হবে:

আমলে নেওয়া পদক্ষেপ

স্ট্রাইডও নেতিবাচক হতে পারে:

যদি পদক্ষেপটি ইতিবাচক হয় তবে বিটম্যাপটি টপ-ডাউন হয়। যদি ধাপটি নেতিবাচক হয় তবে বিটম্যাপটি নীচের দিকে।

তবে আমি এ জাতীয় চিত্র নিয়ে কাজ করি নি এবং এটি আমার নোটের বাইরে।

সম্পর্কিত উত্তর: সি # - বিটম্যাপ থেকে আরজিবি বাফার সি ++ থেকে আলাদা


6

সমস্ত উপস্থাপিত উত্তর ধরে নিবে যে বাইট অ্যারেটিতে একটি পরিচিত ফাইল ফর্ম্যাট উপস্থাপনায় ডেটা রয়েছে, যেমন: জিআইএফ, পিএনজি বা জেপিজি। তবে সম্প্রতি আমি 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;
    }
}

এটি কোনও সমাধানের সামান্য প্রকরণ যা এই সাইটে পোস্ট করা হয়েছিল ।


রেফারেন্স হিসাবে এমএসডিএন: বিটম্যাপ (ইন্ট 32, ইন্ট 32): "এই কনস্ট্রাক্টর ফর্ম্যাট 32 বিপিআরজিবি এর পিক্সেল ফর্ম্যাট গণনা মান সহ একটি বিটম্যাপ তৈরি করে।" যার অর্থ বাইট [0] নীল, বাইট [1] সবুজ, বাইট [2] লাল , বাইট [3] হ'ল আলফা, বাইট [4] নীল, ইত্যাদি।
ব্র্যাক

4
আপনাকে "প্রয়োজনীয়" ব্যবহার করে সমস্ত সংযুক্ত করার জন্য ধন্যবাদ। বেশিরভাগ লোকেরা তা ভুলে যায় এবং তাদের সমস্ত খুঁজে পাওয়া বেদনা।
কেসি ক্রুকস্টন

6

নীচে হিসাবে একটি সহজ পদ্ধতির আছে, আপনি কৌশলটি করতে FromStreamএকটি চিত্রের পদ্ধতি ব্যবহার করতে পারেন, কেবল ব্যবহার করতে ভুলবেন না System.Drawing;

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

5

চেষ্টা (আপডেট)

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

4
বাইট অ্যারে একই বাইট অ্যারে দিয়ে শুরু করার পরে মেমরি স্ট্রিমটিতে বাইট অ্যারে লিখলে তা বোঝা যায় না। আসলে আমি নিশ্চিত নই যে মেমরিস্ট্রিম কনস্ট্রাক্টরে নির্দিষ্ট দৈর্ঘ্যের বাইরে লেখার অনুমতি দেয়।
হলস্টেব্রো

2

আপনি রিটার্ন ইমেজকে কোনও ধরণের পরিবর্তনশীল হিসাবে ঘোষণা করেননি :)

এটি সাহায্য করা উচিত:

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

4
কোড একটি ধারণা হিসাবে দরকারী, তবে অবশ্যই লিখিত হিসাবে কাজ করবে না। রিটার্ন ইমেজ চেষ্টা / ধরা বিভাগের বাইরে ঘোষণা করতে হবে। এছাড়াও রিটার্নইমেজকে 'ক্যাচ' -তে ইনস্ট্যান্ট করতে হবে - আমি একটি একক পিক্সেল বিটম্যাপ তৈরি করি: var চিত্র = নতুন বিটম্যাপ (1, 1); মেমরিস্ট্রিম স্ট্রিম = নতুন মেমোরিস্ট্রিম (); image.Save (স্ট্রিম, ইমেজফর্ম্যাট.জেপিগ); স্ট্রিম.পজিশন = 0;
রেড

2

এটি হোলস্টেব্রয়ের উত্তর, এবং এখানে মন্তব্যগুলি দ্বারা অনুপ্রাণিত: বাইট অ্যারে থেকে একটি চিত্র অবজেক্ট পাওয়া

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



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

প্রথমে এই প্যাকেজটি ইনস্টল করুন:

ইনস্টল-প্যাকেজ সিক্স লেবার্স

[সিক্স ল্যাবর্স.আইজেজশার্প] [১] [১]: https://www.nuget.org/packages/SixLabors.ImageSharp

তারপরে ছবিতে কাস্ট বাইট অ্যারের জন্য নীচের কোডটি ব্যবহার করুন:

Image<Rgba32> image = Image.Load(byteArray); 

কোডের নীচে ইমেজ ফরম্যাট ব্যবহারের জন্য:

IImageFormat format = Image.DetectFormat(byteArray);

মিউটেট চিত্রের জন্য কোডের নীচে ব্যবহার করুন:

image.Mutate(x => x.Resize(new Size(1280, 960)));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.