Strona główna » Algorytmy » Artykuły » Konsolowe Skalowanie
 

Konsolowe Skalowanie

Zadanie

Napisz program, który wczyta od użytkownika pewien wzór złożony z znaków alfanumerycznych oraz skalę s. Następnie wypisz na konsolę ten sam wzór zeskalowany o wczytaną wcześniej wartość. Wczytana wartość skalowanie może być dowolną liczbą rzeczywistą większą od 0.

Przykład

Przypuśćmy, że użytkownik wpisze następujący wzór:

  1. ab
  2. cd

Zadana skala wynosi 2, a więc wzór zostanie powiększony dokładnie 2 razy:

  1. aabb
  2. aabb
  3. ccdd
  4. ccdd

Analiza zadania

Do powiększania wzoru zostanie zastosowana technika najbliższego sąsiada. Metoda ta polega na kopiowaniu sąsiednich wartości w przypadku zwiększania, a jeśli wzór będzie zmniejszany to analogicznie pewne wartości zaczną znikać. W celu rozszerzenia / skrócenia linijki danych należy wyliczyć stosunek starej szerokości do nowej mn, a następnie dla każdej nowej pozycji pobrać wartość pod indeksem, który jest iloczynem aktualna pozycji oraz wyliczonej wartości mn.

Przykładowo rozszerzamy dwukrotnie linijkę ab. W tym celu wyliczamy nową szerokość czyli 4, a następnie przechodzimy do wyliczania wartości. Mnożnik mn wynosi 1/2=0.5. W tabelce zebrano potrzebne informacje:

Nowa pozycja0123
Wyliczona wartość00.511.5
Stara pozycja0011
Znakaabb

Wyliczonej wartości na podstawie indeksu nowej pozycji należy obciąć część ułamkową. Dzięki temu możliwe będzie pobranie wartości z starej linijki. Na koniec obliczona wartość wskazuje indeks pozycji do pobrania z danych.

Implementacja

Poniższa funkcja SkalujWzor() jest rozwiązaniem omawianego problemu. Przyjmuje ona tablicę łańcuchów znaku, gdzie przechowywany jest wzór oraz skalę - liczbę rzeczywistą.

C++C#
Python
  1. def SkalujWzor(dane, skala):
  2.   szer_glowna = len(dane[0])
  3.   wys_glowna = len(dane)
  4.   szer_nowa = szer_glowna * skala
  5.   wys_nowa = wys_glowna * skala
  6.   for y in range(int(wys_nowa)):
  7.     mn_y = wys_glowna / wys_nowa
  8.     for x in range(int(szer_nowa)):
  9.       mn_x = szer_glowna / szer_nowa
  10.       print(dane[(int)(y * mn_y)][(int)(x * mn_x)], end="")
  11.     print()

Na początku pobierana jest akualna szerokość oraz wysokość, a następnie wyliczana nowa szerokość i wysokość. Dla każdej nowej pozycji zeskalowanego obiektu: należy obliczyć, którą wartość należy przepisać z danych. Warto pamiętać, że interpolację przeprowadzamy zarówno wzdłuż szerokości jak i wysokości, a więc potrzebny jest inny mnożnik dla każdej współrzędnej. (W przypadku równomiernego skalowania i kwadratowego obrazka wystarczyłby jeden mnożnik.)

Testowanie funkcji

Test kodu można przeprowadzić używając poniższego fragmentu kodu, który wczyta potrzebne dane, a następnie wypisz wynik na ekran.

C++C#
Python
  1. [w, h] = [int(x) for x in input("Podaj rozmiar wzoru\n w x h = ").split()]
  2. print("Podaj wzór:")
  3. dane = []
  4. for i in range(h):
  5.   line = input()
  6.   dane.append(line)
  7. skala = float(input("Podaj skalę\n s = "))
  8. SkalujWzor(dane, skala)