চিত্র.সেভ (..) একটি জিডিআই + ব্যতিক্রম ছোঁড়ে কারণ মেমরি স্ট্রিম বন্ধ রয়েছে


108

আমি কিছু বাইনারি ডেটা পেয়েছি যা আমি একটি চিত্র হিসাবে সংরক্ষণ করতে চাই। আমি যখন ছবিটি সংরক্ষণ করার চেষ্টা করি তখন এটি ব্যতিক্রম ছুঁড়ে দেয় যদি চিত্রটি তৈরি করতে ব্যবহৃত মেমরি স্ট্রিমটি সংরক্ষণের আগে বন্ধ হয়ে যায়। আমি এটি করার কারণটি হ'ল কারণ আমি গতিশীলভাবে চিত্রগুলি তৈরি করছি এবং এর মতো .. আমার একটি স্মৃতি প্রবাহ ব্যবহার করা দরকার।

এই কোড:

[TestMethod]
public void TestMethod1()
{
    // Grab the binary data.
    byte[] data = File.ReadAllBytes("Chick.jpg");

    // Read in the data but do not close, before using the stream.
    Stream originalBinaryDataStream = new MemoryStream(data);
    Bitmap image = new Bitmap(originalBinaryDataStream);
    image.Save(@"c:\test.jpg");
    originalBinaryDataStream.Dispose();

    // Now lets use a nice dispose, etc...
    Bitmap2 image2;
    using (Stream originalBinaryDataStream2 = new MemoryStream(data))
    {
        image2 = new Bitmap(originalBinaryDataStream2);
    }

    image2.Save(@"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}

স্ট্রিমটি বন্ধ হয়ে কীভাবে আমি কোনও চিত্র সংরক্ষণ করতে পারি সে সম্পর্কে কারও কি কোনও পরামর্শ আছে? চিত্রটি সংরক্ষণের পরে স্ট্রিমটি বন্ধ করার কথা মনে রাখতে আমি বিকাশকারীদের উপর নির্ভর করতে পারি না। প্রকৃতপক্ষে, বিকাশকারীটির কোনও আইডিইএ থাকবে না যে চিত্রটি একটি মেমরি স্ট্রিম ব্যবহার করে তৈরি করা হয়েছিল (কারণ এটি অন্য কোনও কোডে অন্যত্র হয়) happens

আমি সত্যি বিভ্রান্ত :(


1
আমি অন্য মধ্যে @HansPassant থেকে এই মন্তব্যটি পেয়েছিলাম প্রশ্ন । কোডেক ফাইলটি লেখার ক্ষেত্রে সমস্যা দেখা দিলে আপনি এই ব্যতিক্রমটি পাবেন। যোগ করার জন্য একটি ভাল ডিবাগিং স্টেটমেন্টটি হ'ল System.IO.File.WriteAllText (পাথ, "পরীক্ষা") সংরক্ষণ করুন () কল করার আগে, এটি ফাইলটি তৈরি করার প্রাথমিক ক্ষমতাটি যাচাই করে। আপনি এখন একটি ভাল ব্যতিক্রম পাবেন যা আপনাকে কী ভুল করেছে তা বলে দেয়।
হুয়ান কার্লোস ওরোপেজা

আপনার ইমেজ 2 করা উচিত block usingব্লকের ভিতরে সংরক্ষণ করুন । আমি মনে করি originalBinaryDataStream2 ব্যবহার শেষে স্বয়ংক্রিয়ভাবে নিষ্পত্তি হয়েছিল। এবং এটি ব্যতিক্রম নিক্ষেপ করবে।
তায়ঙ্গুয়েন

উত্তর:


172

এটি একটি মেমরিস্ট্রিম হিসাবে, সত্যই আপনার স্ট্রিমটি বন্ধ করার দরকার নেই - যদি না করেন তবে খারাপ কিছু ঘটবে না, যদিও স্পষ্টতই যে কোনওভাবে নিষ্পত্তিযোগ্য কোনও কিছু নিষ্পত্তি করা ভাল অভ্যাস। ( এই বিষয়ে আরও জানতে এই প্রশ্নটি দেখুন ))

তবে আপনার বিটম্যাপটি নিষ্পত্তি করা উচিত - এবং এটি আপনার জন্য স্ট্রিমটি বন্ধ করে দেবে। মূলত একবার আপনি বিটম্যাপ কনস্ট্রাক্টরকে একটি স্ট্রিম দেওয়ার পরে এটি স্ট্রিমটির "মালিকানাধীন" থাকে এবং আপনার এটি বন্ধ করা উচিত নয়। যেমন কনস্ট্রাক্টরের জন্য ডকস বলেছেন:

বিটম্যাপের আজীবন আপনার অবশ্যই স্ট্রিমটি উন্মুক্ত রাখতে হবে।

আপনি যখন বিটম্যাপটি নিষ্পত্তি করবেন তখন স্ট্রিমটি বন্ধ করার প্রতিশ্রুতি দেওয়ার মতো কোনও ডক্স পাচ্ছি না, তবে আপনি এটি মোটামুটি সহজেই যাচাই করতে সক্ষম হবেন।


2
অসাধারণ! এটি একটি দুর্দান্ত উত্তর জন। নিখুঁত ধারণা তৈরি করে (এবং আমি ডক্সের স্ট্রিমটি সম্পর্কে কিছুটা মিস করেছি)। দুই থাম্বস আপ! আমি যখন যাব সে সম্পর্কে আমি প্রতিবেদন করব :)
শুদ্ধ.ক্রোম

আমরা যদি CA2000 রুল মানতে চাই তবে এ সম্পর্কে কীভাবে যেতে হবে তার কোনও মন্তব্য? (
এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms182289.aspx

@ পেট্রিক: এটি কেবল প্রযোজ্য নয় - আপনি মূলত সম্পদের মালিকানা স্থানান্তর করেছেন। আপনি যে নিকটে আসতে পারেন সেটি হ'ল "ননক্লোজিংস্ট্রিম" র‍্যাপার তৈরি করা যা ডিসপোজ কলটিকে উপেক্ষা করে। আমি মনে করি আমার একটি মিসকিলের মধ্যে থাকতে পারে - নিশ্চিত নয় ...
জন স্কিটি

জোন তথ্যের জন্য ধন্যবাদ। আমার জন্য, কিছু অদ্ভুত কারণে এটি স্থানীয় দেব পরিবেশে নিষ্পত্তি () এর সাথেও কাজ করে যাচ্ছিল তবে উত্পাদনে কাজ করে নি।
অক্সন

92

জিডিআই + তে একটি জেনেরিক ত্রুটি ঘটেছে। এছাড়াও এখান থেকে হতে পারে পাথ সংরক্ষণ ভুল ! আমাকে খেয়াল করতে আধা দিন সময় নিয়েছে। সুতরাং নিশ্চিত হয়ে নিন যে আপনি চিত্রটি সংরক্ষণ করার জন্যও দু'বার চেক করেছেন।


4
আমি খুশী আমি এই দেখেছি, আমার পথ ছিল C\Users\mason\Desktop\pic.png। নিখোঁজ কোলন! আমি এটা খেয়াল করার আগে চিরকাল কাটাতাম।
রাজমিস্ত্রি

4
ভুলটির অর্থ হ'ল যে ফোল্ডারটি আপনি চিত্রটি সংরক্ষণ করতে চান তার অস্তিত্ব নেই।
রোমার

14

সম্ভবত এটি উল্লেখযোগ্য যে যদি সি: \ টেম্প ডিরেক্টরিটি উপস্থিত না থাকে তবে আপনার স্ট্রিমটি এখনও বিদ্যমান থাকলেও এটি এই ব্যতিক্রমটিকে ছুঁড়ে ফেলবে।


+1 এই ব্যতিক্রমটি বিভিন্ন পরিস্থিতিতে ঘটেছে বলে মনে হচ্ছে। অবৈধ পথ হ'ল আমি আজ মুখোমুখি।
কર્ક ব্রডহર્স্ট

4

আমার একই সমস্যা ছিল কিন্তু আসলে কারণটি হ'ল অ্যাপ্লিকেশনটির সিটিতে ফাইল সংরক্ষণের অনুমতি ছিল না যখন আমি "ডি: \ .." এ পরিবর্তন করেছিলাম তবে ছবিটি সংরক্ষণ করা হয়েছে।


2

বিটম্যাপটি অনুলিপি করুন। আপনাকে বিটম্যাপের আজীবন স্ট্রিমটি উন্মুক্ত রাখতে হবে।

কোনও চিত্র আঁকানোর সময়: সিস্টেম.আরুনটাইম.ইনটার্প সার্ভিসস.আন্তরের অভিজ্ঞতা: জিডিআইতে একটি জেনেরিক ত্রুটি ঘটেছে

    public static Image ToImage(this byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes))
        using (var image = Image.FromStream(stream, false, true))
        {
            return new Bitmap(image);
        }
    }

    [Test]
    public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
    {
        var imageBytes = File.ReadAllBytes("bitmap.bmp");

        var image = imageBytes.ToImage();

        image.Save("output.bmp");
    }

1
এটি ঠিক কাজ করে না; টোআইমেজে আপনার কোডটিতে (), স্থানীয় "চিত্র" এর সঠিকরূপে একটি .RawFormat থাকবে মূল ফাইলটি যা ছিল (jpeg বা png, ইত্যাদি), তবে ToImage () এর রিটার্ন মানটি অপ্রত্যাশিতভাবে থাকবে। রা ফর্ম্যাট মেমরিবিএমপি।
প্যাট্রিক জাজালাপস্কি

তবে RawFormatবিষয়টি কীভাবে নিশ্চিত তা নিশ্চিত নয় । আপনি যে ব্যবহার করতে চান তাহলে, পথ ধরে বস্তুর কোথাও থেকে এটা পুনরুদ্ধার, কিন্তু সংরক্ষণ আপনি আসলে চান যাই হোক না কেন টাইপ করবেন, সাধারণভাবে করার আছে
নায়ারগডস

2

আপনি বিটম্যাপের অন্য একটি অনুলিপি তৈরি করার চেষ্টা করতে পারেন:

using (var memoryStream = new MemoryStream())
{
    // write to memory stream here

    memoryStream.Position = 0;
    using (var bitmap = new Bitmap(memoryStream))
    {
        var bitmap2 = new Bitmap(bitmap);
        return bitmap2;
    }
}

2

আমি সিট্রিক্স থেকে চেষ্টা করার সময় এই ত্রুটিটি আমার কাছে ঘটেছিল। ইমেজ ফোল্ডারটি সার্ভারে সি: to এ সেট করা হয়েছিল, যার জন্য আমার কোনও অধিকার নেই। একবার চিত্র ফোল্ডারটি একটি ভাগ করা ড্রাইভে সরানো হলে ত্রুটিটি চলে গেছে।


1

জিডিআই + তে একটি জেনেরিক ত্রুটি ঘটেছে। এটি চিত্রের সংরক্ষণের পথের সমস্যার কারণে ঘটতে পারে, আমার এই ত্রুটিটি পেয়েছিল কারণ আমার সঞ্চয়ের পথটি দীর্ঘ,


1

আমি এই ত্রুটিটি পাচ্ছিলাম, কারণ আমি যে অটোমেটেড পরীক্ষাটি চালিয়ে যাচ্ছিলাম, সেগুলি স্ন্যাপশটগুলি কোনও ফোল্ডারে সংরক্ষণ করার চেষ্টা করছিল যা বিদ্যমান ছিল না। আমি ফোল্ডারটি তৈরি করার পরে, ত্রুটিটি সমাধান হয়েছে


0

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


0

যখন আমি কোনও চিত্রকে পথে চালানোর চেষ্টা করছিলাম তখন এটি আমার সাথে উপস্থিত হয়েছিল

C:\Program Files (x86)\some_directory

এবং .exeপ্রশাসক হিসাবে চালানোর জন্য মৃত্যুদন্ড কার্যকর করা হয়নি, আমি আশা করি এটি একই সমস্যাযুক্ত কাউকে সাহায্য করতে পারে।


0

আমার জন্য নীচের কোডটি A generic error occurred in GDI+লাইনে ক্র্যাশ হয়েছে যা একটিতে সংরক্ষণ করেMemoryStream । কোডটি একটি ওয়েব সার্ভারে চলছে এবং আমি এটি চালাচ্ছি এবং অ্যাপ্লিকেশন পুলটি চালাচ্ছি যা সাইটটি চালাচ্ছিল।

জিডিআই + তে অবশ্যই কিছু অভ্যন্তরীণ ত্রুটি ঘটেছে

    private static string GetThumbnailImageAsBase64String(string path)
    {
        if (path == null || !File.Exists(path))
        {
            var log = ContainerResolver.Container.GetInstance<ILog>();
            log.Info($"No file was found at path: {path}");
            return null;
        }

        var width = LibraryItemFileSettings.Instance.ThumbnailImageWidth;

        using (var image = Image.FromFile(path))
        {
            using (var thumbnail = image.GetThumbnailImage(width, width * image.Height / image.Width, null, IntPtr.Zero))
            {
                using (var memoryStream = new MemoryStream())
                {
                    thumbnail.Save(memoryStream, ImageFormat.Png); // <= crash here 
                    var bytes = new byte[memoryStream.Length];
                    memoryStream.Position = 0;
                    memoryStream.Read(bytes, 0, bytes.Length);
                    return Convert.ToBase64String(bytes, 0, bytes.Length);
                }
            }
        }
    }

0

আমি যখন ডাব্লুপিএফ অ্যাপে একটি সাধারণ চিত্র সম্পাদনা করার চেষ্টা করছিলাম তখন আমি এই ত্রুটিটি পেরিয়ে এসেছি।

বিটম্যাপে একটি চিত্র উপাদানটির উত্স সেট করা ফাইল সংরক্ষণকে বাধা দেয়। এমনকি উত্স = নাল নির্ধারণ করা ফাইলটি প্রকাশ করবে বলে মনে হয় না।

এখন আমি চিত্রটিকে কখনই চিত্রের উত্স হিসাবে উত্স হিসাবে ব্যবহার করি না, তাই আমি সম্পাদনার পরে ওভাররাইট করতে পারি!

সম্পাদনা

ক্যাসিপশন সম্পত্তি সম্পর্কে শুনে (@ নায়ারগডসকে ধন্যবাদ) আমি সমাধানটি পেয়েছি: সুতরাং বিটম্যাপ কন্সট্রাক্টর ব্যবহার না করে আমাকে অবশ্যই সেটিংয়ের পরে উরি সেট করতে হবে CacheOption BitmapCacheOption.OnLoad(( Image1নীচে ডাব্লুপিএফ Imageউপাদানটি রয়েছে)

পরিবর্তে

Image1.Source = new BitmapImage(new Uri(filepath));

ব্যবহার করুন:

var image = new BitmapImage();
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filepath);
image.EndInit();
Image1.Source = image;

এটি দেখুন: ডাব্লুপিএফ চিত্রের ক্যাচিং


1
BitmapCacheOption.OnLoadলোডিং উত্স থেকে সংযোগ বিচ্ছিন্ন করার জন্য ডাব্লুপিএফ চিত্রগুলির একটি নির্দিষ্ট প্যারামিটার রয়েছে ।
নায়ারগডস

আপনাকে @ নায়ারগডসকে ধন্যবাদ, আপনার মন্তব্য না হওয়া পর্যন্ত আমি সঠিক প্রশ্ন জিজ্ঞাসা করতে ব্যর্থ হই
এমকেবি

0

এই কোড ব্যবহার করে দেখুন:

static void Main(string[] args)
{
    byte[] data = null;
    string fullPath = @"c:\testimage.jpg";

    using (MemoryStream ms = new MemoryStream())
    using (Bitmap tmp = (Bitmap)Bitmap.FromFile(fullPath))
    using (Bitmap bm = new Bitmap(tmp))
    {
        bm.SetResolution(96, 96);
        using (EncoderParameters eps = new EncoderParameters(1))
        {   
            eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bm.Save(ms, GetEncoderInfo("image/jpeg"), eps);
        }

        data = ms.ToArray();
    }

    File.WriteAllBytes(fullPath, data);
}

private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
        ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();

        for (int j = 0; j < encoders.Length; ++j)
        {
            if (String.Equals(encoders[j].MimeType, mimeType, StringComparison.InvariantCultureIgnoreCase))
                return encoders[j];
        }
    return null;
}

0

আমি চিত্রগুলি পুনরায় আকার দিতে ইমেজপ্রসেসর ব্যবহার করেছি এবং একদিন আমি "জিডিআই + তে একটি জেনেরিক ত্রুটি ঘটেছে" ব্যতিক্রম পেয়েছি।

কিছুক্ষণ দেখার পরে আমি অ্যাপ্লিকেশন পুলটি পুনর্ব্যবহার করার চেষ্টা করেছি এবং এটি কাজ করে b তাই আমি এখানে এটি নোট করি, আশা করি এটি সহায়তা করবে;)

চিয়ার্স

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.