Ejemplo n.º 1
0
        //Funkcja wywoływana dla każdego obrazu. Odpowiada za skalowanie
        public void interpolate(object param)
        {
            //Rzutowanie typu - otrzymanie parametrów funkcji
            Polecenie paramP = param as Polecenie;
            string    src    = paramP.inputFile;
            string    dst    = paramP.outputFile;

            //Podział ścieżki źródłowej na segmenty foldery i pliki
            string[] split = src.Split(new[] { "\\" }, StringSplitOptions.None);
            //Wyłuskanie rozszerzenia pliku z ostatniego segmentu ścieżki źródłowej
            string extension = split.Last().Split(new char[] { '.' }).Last().ToLower();
            //Ustawienie formatu pliku wynikowego
            ImageFormat format;

            switch (extension)
            {
            case "jpg":
            {
                format = ImageFormat.Jpeg;
                break;
            }

            case "bmp":
            {
                format = ImageFormat.Bmp;
                break;
            }

            case "png":
            {
                format = ImageFormat.Png;
                break;
            }

            default:
                format = ImageFormat.Jpeg;
                break;
            }
            //Dodanie do ścieżki docelowej nazwy pliku z rozszerzeniem
            dst = dst + "\\" + split.Last();

            //Tylko 1 wątek na raz może podjąć próbę zaalokowania pamięci
            memoryAllocation.WaitOne();
            Image  srcImage  = null;
            Bitmap srcBitmap = null;
            Bitmap dstBitmap = null;

            //Tak długo, jak nie udało się zaalokować pamięci na obraz źródłowy,
            //jego bitmapę i bitmapę docelową...
            while (srcBitmap == null || dstBitmap == null || srcImage == null)
            {
                if (srcImage == null)
                {
                    try
                    {
                        //Załaduj obraz z dysku do pamięci
                        srcImage = Image.FromFile(src);
                    }
                    catch (OutOfMemoryException)
                    {
                        //Jeżeli się nie udało, przypisz null
                        srcImage = null;
                    }
                }
                if (srcImage != null && srcBitmap == null)
                {
                    try
                    {
                        //Załaduj bitmapę z obrazu źródłowego
                        srcBitmap = new Bitmap(srcImage);
                    }
                    catch (Exception)
                    {
                        //Jeżeli się nie udało, przypisz null
                        srcBitmap = null;
                    }
                }
                if (dstBitmap == null)
                {
                    try
                    {
                        //Utworz bitmapę na obraz docelowy
                        dstBitmap = new Bitmap(dstWidth, dstHeight);
                    }
                    catch (Exception)
                    {
                        //Jeżeli się nie udało, przypisz null
                        dstBitmap = null;
                    }
                }
                //Jeżeli nie udało się zaalokować pamięci na obraz źródłowy i bitmapy
                if (srcBitmap == null || dstBitmap == null || srcImage == null)
                {
                    //"Zabierz" dla siebie semaforę oczekującą na zwolniene pamięci
                    awaitingMemory.WaitOne();
                    //Czekaj, aż inny wątek zwolni semaforę (zrobi to po zwolnieniu używanych zasobów)
                    //Górny limit czasu oczekiwania wynosi 5 minut
                    awaitingMemory.WaitOne(300000);
                    //Zwolnij zabraną semaforę
                    try { awaitingMemory.Release(); }
                    catch (SemaphoreFullException) { }
                }
            }
            //Po udanej alokacji pamięci, zwolnij semaforę
            memoryAllocation.Release();

            //Zablokuj bitmapy do użytku przez niezarządzalny kod
            BitmapData srcData = srcBitmap.LockBits(
                new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height),
                ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);

            BitmapData dstData = dstBitmap.LockBits(
                new Rectangle(0, 0, dstBitmap.Width, dstBitmap.Height),
                ImageLockMode.WriteOnly,
                PixelFormat.Format32bppArgb);

            unsafe
            {
                //Wskaźniki na tablice pikseli
                byte *srcPtr = (byte *)srcData.Scan0;
                byte *dstPtr = (byte *)dstData.Scan0;
                //Wybór funkcji asm/C
                if (language == 0)
                {
                    interpolateAsm(srcPtr, dstPtr, srcImage.Width,
                                   srcImage.Height, dstWidth, dstHeight);
                }
                else
                {
                    interpolateC(srcPtr, dstPtr, srcImage.Width,
                                 srcImage.Height, dstWidth, dstHeight);
                }
            }
            //Odblokowanie bitmap po ich wykorzystaniu przez funkcje interpolacji
            srcBitmap.UnlockBits(srcData);
            dstBitmap.UnlockBits(dstData);
            try
            {
                //Zapis docelowego obrazu do pliku
                dstBitmap.Save(dst, format);
            }
            catch (ExternalException)
            {
                MessageBox.Show("Nie mozna zapisac do pliku\n" + dst);
            }
            //Zwolnienie zasobów
            dstBitmap.Dispose();
            srcBitmap.Dispose();
            srcImage.Dispose();
            dstBitmap = null;
            srcBitmap = null;
            srcImage  = null;
            //Tylko 1 wątek na raz może poinformować o zwolnieniu swoich zasobów
            checkingAwaitingMemory.WaitOne();
            //Zwolnij semaforę, informując wątek oczekujący na zasoby o ich zwolnieniu
            awaitingMemory.WaitOne(0);
            awaitingMemory.Release();
            //Zwolnij semaforę - kolejny wątek może informować o zwolnieniu zasobów
            checkingAwaitingMemory.Release();

            this.progressBar1.Invoke(new Action(() => {
                //Zwiększ postęp na pasku postępu
                progressBar1.PerformStep();
                //Jeżeli pasek się wypełnił, to zadanie zostało wykonane.
                //Wykonaj podsumowanie
                if (progressBar1.Value == progressBar1.Maximum)
                {
                    //Skończ liczyć czas
                    watch.Stop();
                    //Uaktywnij przyciski w GUI
                    convertBtn.Enabled      = true;
                    destBtn.Enabled         = true;
                    sourceSelectBtn.Enabled = true;
                    //Informacja tekstowa o zakończonej pracy
                    infoLabel.Text = "Skalowanie zakończone!";

                    //Okno informujące o czasie trwania operacji
                    MessageBox.Show("Konwersja trwala :" + watch.ElapsedMilliseconds.ToString() + "ms.");
                }
            }));
        }
Ejemplo n.º 2
0
        //Funkcja wywoływana po naciśnięciu przycisku "Skaluj"
        private void convertBtn_Click(object sender, EventArgs e)
        {
            //Jeżeli nie wybrano obrazow
            if (selectedImages.Count == 0)
            {
                //Nie rób nic
                return;
            }
            //Ustawienie liczby pracujących wątków na dostępne wątki
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(threadCount, threadCount);
            ThreadPool.SetMinThreads(threadCount, threadCount);
            //Przypisanie do zmiennej wyboru użytkownika dot. funkcji skalującej
            if (asmRadioBtn.Checked == true)
            {
                language = 0;
            }
            else
            {
                language = 1;
            }
            //Zablokowanie możliwości klikania przycisków
            convertBtn.Enabled      = false;
            destBtn.Enabled         = false;
            sourceSelectBtn.Enabled = false;

            //Utworzenie semafor
            memoryAllocation       = new Semaphore(1, 1);
            awaitingMemory         = new Semaphore(1, 1);
            checkingAwaitingMemory = new Semaphore(1, 1);
            //Pobranie z kontrolek rozdzielczości docelowej zdjęć
            dstWidth  = (int)widthBox.Value;
            dstHeight = (int)heightBox.Value;

            infoLabel.Text = "Sprawdzanie zasobów...";
            //Tymczasowa bitmapa
            Bitmap tempDst;

            try
            {
                //Sprawdzenie, czy można zaalokować wystarczająco pamięci na obrazek docelowy
                tempDst = new Bitmap((int)widthBox.Value, (int)heightBox.Value);
            }
            catch (Exception)
            {
                MessageBox.Show("Nie można zaalokować pamięci na obrazek docelowy.");
                //Jeżeli nie można, nie ma sensu liczyć dalej
                return;
            }
            //Struktura na pliki, które będą obsługiwane, tj. wystarczy pamięci na ich skalowanie
            List <string> imagesToProcess = new List <string>();

            //Ustawienie paska postępu
            progressBar1.Maximum = selectedImages.Count;
            progressBar1.Value   = 0;
            new Thread(() =>
            {
                //Dla każdego obrazka
                foreach (string imgPath in selectedImages)
                {
                    try
                    {
                        //Spróbuj załadować do pamięci i utworzyć z niego bitmapę
                        Image srcImg = Image.FromFile(imgPath);
                        Bitmap bmp   = new Bitmap(srcImg);
                        //Jeżeli udało się zarezerwować zasoby, dodaj obrazek do listy
                        imagesToProcess.Add(imgPath);
                        //Zwolnij użyte zasoby
                        bmp.Dispose();
                        srcImg.Dispose();
                        progressBar1.Invoke(new Action(() =>
                        {
                            //Aktualizuj postęp
                            progressBar1.PerformStep();
                            //Po przetworzeniu wszystkich zdjęć
                            if (progressBar1.Value == progressBar1.Maximum)
                            {
                                //Przygotuj i uruchom zegar zliczający czas trwania skalowania
                                watch = new System.Diagnostics.Stopwatch();
                                watch.Start();
                                infoLabel.Text = "Sprawdzono pomyślnie. Trwa skalowanie...";
                                //Jeżeli nie wszystkie obrazy uda się przetworzyć, wyświetl komunikat
                                if (imagesToProcess.Count != selectedImages.Count)
                                {
                                    MessageBox.Show("Zasoby sprzetowe pozwolą obsłużyć " + imagesToProcess.Count
                                                    + " z " + selectedImages.Count + " wybranych zdjęć.");
                                }
                                //Ustawienie paska postępu
                                progressBar1.Value   = 0;
                                progressBar1.Maximum = imagesToProcess.Count;
                                progressBar1.Step    = 1;
                                //Jeżeli katalog źródłowy = katalog docelowy
                                if (createOut)
                                {
                                    createOut = false;
                                    //Dodaj do katalogu docelowego końcówkę "out"
                                    dstDir += "\\out";
                                    try
                                    {
                                        //Spróbuj utworzyć katalog docelowy
                                        System.IO.Directory.CreateDirectory(dstDir);
                                    }
                                    catch (UnauthorizedAccessException)
                                    {
                                        //Jeżeli jest to niemożliwe, wyświetl odpowiedni komunikat i zakończ
                                        MessageBox.Show("Nie mam uprawnien do utworzenia katalogu out...");
                                        destBtn.Invoke(new Action(() => {
                                            destBtn.Enabled         = true;
                                            sourceSelectBtn.Enabled = true;
                                            convertBtn.Enabled      = true;
                                        }));
                                        return;
                                    }
                                }
                                //Dla każdego obrazu do przetworzenia
                                foreach (string image in imagesToProcess)
                                {
                                    //Przygotuj obiekt zawierający argumenty funkcji
                                    Polecenie param  = new Polecenie();
                                    param.inputFile  = image;
                                    param.outputFile = dstDir;
                                    //Kolejkuj zdjęcie
                                    ThreadPool.QueueUserWorkItem(new WaitCallback(interpolate), param);
                                }
                            }
                        }));
                    }
                    catch (Exception) //łapiemy out of memory i przy tworzeniu bitmapy
                    {
                        //nic nie robimy, po prostu na koniec obsluzymy mniej obrazow;
                    }
                }
            }).Start();
        }