4

編集:私はOutOfMemoryExceptionが処理されないままになり続けます、それは私が分離されたストレージに画像を保存する方法だと思います、私はそれを保存する前に画像のサイズを減らす方法で私の問題を解決できると思いますか?(画像を保存する場所にコードを追加)

分離ストレージから画像を開いているときに100を超える画像があり、それらの画像をループしたいのですがOutOfMemory Exception、ストーリーボードに約100〜150の画像が読み込まれている場合に表示されます。この例外をどのように処理できますか。すでに画像の解像度を下げています。この例外を処理してアプリのクラッシュを防ぐにはどうすればよいですか?

ここのこの行で例外が発生します

image.SetSource(isStoreTwo.OpenFile(projectFolder + "\\MyImage" + i + ".jpg", FileMode.Open, FileAccess.Read));//images from isolated storage

これが私のコードです

private void OnLoaded(object sender, RoutedEventArgs e)
    {


        IsolatedStorageFile isStoreTwo = IsolatedStorageFile.GetUserStoreForApplication();



        try
        {
            storyboard = new Storyboard
            {
                //RepeatBehavior = RepeatBehavior.Forever
            };

            var animation = new ObjectAnimationUsingKeyFrames();

            Storyboard.SetTarget(animation, projectImage);
            Storyboard.SetTargetProperty(animation, new PropertyPath("Source"));


            storyboard.Children.Add(animation);
            for (int i = 1; i <= savedCounter; i++)
            {
                BitmapImage image = new BitmapImage();

                image.SetSource(isStoreTwo.OpenFile(projectFolder + "\\MyImage" + i + ".jpg", FileMode.Open, FileAccess.Read));//images from isolated storage

                var keyframe = new DiscreteObjectKeyFrame
                {

                    KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(100 * i)),
                    Value = image
                };

                animation.KeyFrames.Add(keyframe);
            }
        }
        catch (OutOfMemoryException exc)
        {

            //throw;

        }



        Resources.Add("ProjectStoryBoard", storyboard);
        storyboard.Begin();
    }

編集 これは私が隔離されたストレージに画像を保存する方法です、私はこれが私の問題を解決できる場所だと思います、隔離されたストレージに保存するときに画像のサイズを減らすにはどうすればよいですか?

    void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
    {

        string fileName = folderName+"\\MyImage" + savedCounter + ".jpg";

        try
        {  

            // Save picture to the library camera roll.
            //library.SavePictureToCameraRoll(fileName, e.ImageStream);



            // Set the position of the stream back to start
            e.ImageStream.Seek(0, SeekOrigin.Begin);

            // Save picture as JPEG to isolated storage.
            using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
                {

                    // Initialize the buffer for 4KB disk pages.
                    byte[] readBuffer = new byte[4096];
                    int bytesRead = -1;

                    // Copy the image to isolated storage. 
                    while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                    {
                        targetStream.Write(readBuffer, 0, bytesRead);
                    }

                }

            }




        }
        finally
        {
            // Close image stream
            e.ImageStream.Close();
        }

    }

よろしくお願いします。

4

7 に答える 7

7

イメージをメモリにロードすると非圧縮になるため、ディスク上のイメージのサイズは関係ありません。画像に必要なメモリは約(stride * height)です。strideでありwidth * bitsPerPixel)/8、次の4バイトの倍数に切り上げられます。したがって、1024x768でピクセルあたり24ビットの画像は、約2.25MBを使用します。

画像のサイズを把握し、圧縮せずに、その数値を使用してメモリ要件を決定する必要があります。

于 2012-04-13T02:36:21.027 に答える
5

StoryBoardを作成するためにすべての画像を同時にメモリに保存しているため、OutOfMemory例外が発生します。画像を画面に表示するために必要な非圧縮のビットマップサイズを克服することはできないと思います。

したがって、これを乗り越えるには、エラーを修正しようとするのではなく、目標について考える必要があります。Xミリ秒ごとに新しい画像を順番に表示することが目標である場合は、いくつかのオプションがあります。

  1. StoryBoardsを引き続き使用しますが、OnCompletedイベントを使用してそれらをチェーンします。このようにして、一度にすべてを作成する必要はありませんが、次のいくつかを生成するだけで済みます。ただし、100ミリ秒ごとに画像を変更する場合は、十分な速度ではない可能性があります。

  2. ここでの私の答えに記載されているように、CompositionTarget.Renderingを使用します。(現在のソリューションのようにすべてをプリロードするのではなく)次のメモリをプリロードするだけの場合、これはおそらく最小量のメモリを消費します。ただし、経過時間を手動で確認する必要があります。

  3. あなたがしていることを再考してください。あなたがあなたが何をしているのかを述べるならば、人々はより多くの選択肢を持っているかもしれません。

于 2012-04-16T14:53:39.983 に答える
1

投稿の上部にある編集に答えるには、ImageResizerを試してください。NuGetパッケージとHanselBlogエピソードがあります。明らかに、これはAsp.Netベースですが、シナリオで機能するようにそれを処理できると確信しています。

于 2012-04-17T09:54:01.933 に答える
1

通常、設計レイヤーでこの種の問題に取り組む方がうまくいきます。

一部の構成を介して実行環境についてアプリケーションをスマートにすると、アプリケーションがより堅牢になります。たとえば、使用可能なメモリに基づいて、画像サイズ、画像数、画質などの変数を定義し、アプリの実行時にこれらの変数を設定できます。したがって、アプリケーションは常に機能します。高メモリマシンでは高速、低メモリマシンでは低速。しかし、決してクラッシュしません。(管理された環境で作業することは、環境について心配する必要がないことを意味するとは思わないでください...設計は常に重要です)

また、 LazyLoadingのような既知のデザインパターンがいくつかあります。

于 2012-04-20T13:02:06.413 に答える
0

わかりました。画像(1024x768)のmemsizeは少なくとも3 mb(argb)です。

ObjectAnimationUsingKeyFramesが内部でどのように機能するかわからない。おそらく、アニメーションのデータを失うことなく、BitmapImage(およびKeyFrames)のインスタンスを破棄することでgcを強制することができます。(不可能です、コメントを参照してください!)

于 2012-04-13T01:18:52.747 に答える
0

特にWindowsPhoneについてはわかりませんが、.net winformsでは、長時間実行されるタスクを実行するときに別のスレッドを使用する必要があります。BackgroundWorkerまたは同等のものを使用していますか?ファイナライザスレッドがブロックされる可能性があります。これにより、画像のリソースが破棄されなくなります。UIスレッドとは別のスレッドを使用すると、Disposeメソッドを自動的に実行できるようになります。

于 2012-04-13T01:43:58.093 に答える
0

コメントの1つに基づいて、タイムラプスアプリを作成しています。WP7用の商用タイムラプスアプリは、画像を静止画ではなくビデオに圧縮します。例:タイムラプスプロ

ビデオ再生の全体的なポイントは、類似した、または時間に関連する画像を、再生に大量のメモリを必要としない高度に圧縮されたストリームに減らすことです。

ビデオにエンコードする機能をアプリで追加できる場合は、ビデオプレーヤーをエミュレートしようとする問題を回避できます(数百の単一のフル解像度フレームをフリックブックとして使用)。

画像をビデオサーバー側に処理することも別のオプションかもしれません(ただし、カメラ内ほどフレンドリーではありません)。

于 2012-04-18T16:10:27.037 に答える