Próbuję użyć gnuplot 5.0, aby wykreślić tablicę 2D danych bez marginesów, ramek lub osi ... tylko obraz 2D (.png lub .jpg) reprezentujący niektóre dane. Chciałbym mieć każdy element tablicy odpowiada dokładnie jeden piksel w obrazie z żadnym skalowanie / interpolacji etc i bez dodatkowych białych pikseli na krawędziach.
Do tej pory, kiedy próbuję ustawić marginesy na 0, a nawet przy użyciu pixels
flagi, wciąż jestem z rzędem białych pikseli po prawej i górnej granicy obrazu.
Jak mogę uzyskać tylko plik obrazu z reprezentacją tablicy danych piksel po pikselu i niczym więcej?
skrypt gnuplot:
#!/usr/bin/gnuplot --persist
set terminal png size 400, 200
set size ratio -1
set lmargin at screen 0
set rmargin at screen 1
set tmargin at screen 0
set bmargin at screen 1
unset colorbox
unset tics
unset xtics
unset ytics
unset border
unset key
set output "pic.png"
plot "T.dat" binary array=400x200 format="%f" with image pixels notitle
Przykładowe dane z Fortran 90:
program main
implicit none
integer, parameter :: nx = 400
integer, parameter :: ny = 200
real, dimension (:,:), allocatable :: T
allocate (T(nx,ny))
T(:,:)=0.500
T(2,2)=5.
T(nx-1,ny-1)=5.
T(2,ny-1)=5.
T(nx-1,2)=5.
open(3, file="T.dat", access="stream")
write(3) T(:,:)
close(3)
end program main
x y z
formacie listy?Odpowiedzi:
Niektóre terminale gnuplot implementują „z obrazem”, tworząc osobny plik png zawierający obraz, a następnie łącząc się z nim wewnątrz wynikowego wykresu. Bezpośrednie użycie tego osobnego pliku obrazu png pozwoli uniknąć problemów z układem strony, marginesami itp. Tutaj używam terminala canvas. Sama fabuła zostaje wyrzucona; trzymamy tylko plik png utworzony z pożądanej treści.
źródło
set term tikz externalimages
a terminal resetuje licznik za każdym „ustalonym terminem”. Nie możesz używaćset output "/dev/null"
z tikz, ale jeśli to nie zadziała, aby tłumić wyjście, możesz nie przejmować się. Terminale tkcanvas i svg to inne możliwości, ale zewnętrzny mechanizm png zależy od wersji gnuplot i opcji kompilacji.Nie używaj gnuplot.
Zamiast tego napisz skrypt, który odczytuje dane i konwertuje je na jeden z formatów Portable Anymap . Oto przykład w Pythonie:
Jeśli możesz zmodyfikować program, który generuje plik danych, możesz nawet pominąć powyższy krok i zamiast tego wygenerować dane bezpośrednio w formacie PNM.
Tak czy inaczej, możesz użyć ImageMagick, aby przekonwertować obraz na wybrany format:
źródło
imwrite
Funkcji tej można użyć do zapisania danych 2D jako obrazu PNG.gnuplot
, skorzystam z niejmatplotlib
(zobacz moją odpowiedź poniżej). Jest to świetny wkład, ale technicznie pytanie / zlecenie wymagagnuplot
rozwiązania, które wydaje się nieodpowiednie do tego konkretnego zadania.To powinno być łatwe zadanie, jednak najwyraźniej tak nie jest. Poniższe może być (kłopotliwe) rozwiązanie, ponieważ wszystkie inne próby zakończyły się niepowodzeniem. Podejrzewam, że w pewnej bibliotece graficznej występuje problem, którego prawdopodobnie nie można rozwiązać jako użytkownik gnuplot.
Wspomniałeś, że dane macierzy ASCII również są w porządku. „Sztuczka” polega tutaj na wykreślaniu danych, w
with lines
których dane są „przerywane” pustymi liniami, w zasadzie rysowaniem pojedynczych punktów. Zaznacz to, jeśli chcesz przenieść plik danych 1: 1 do bloku danych .Jednakże, jeśli nie jest to już wystarczająco dziwne, wydaje się, że działa dla
png
igif
terminal, ale nie dlapngcairo
lubwxt
. Myślę, że to obejście jest prawdopodobnie powolne i nieefektywne, ale przynajmniej tworzy pożądane wyniki. Nie jestem pewien, czy istnieje ograniczenie rozmiaru. Testowany przy 100 x 100 pikseli z Win7, gnuplot 5.2.6. Komentarze i ulepszenia są mile widziane.Kod:
Wynik: (100 x 100 pikseli)
(powiększony z czarnym tłem):
Obraz o wymiarach 400 x 200 pikseli (zajmuje około 22 sekund na moim 8-letnim laptopie).
źródło
x
iy
. To wciąż działa, jeśliSizeX
iSizeY
nie są równe. Poprawię kod.Data2
?Czego ostatecznie użyłem, aby uzyskać to, czego potrzebowałem, mimo że pytanie / zlecenie wymaga
gnuplot
rozwiązania:matplotlib
ma funkcję matplotlib.pyplot.imsave, która robi to, czego szukałem ... tj. wykreśla „tylko piksele danych” i nie ma dodatków takich jak granice, marginesy, osie itp. Pierwotnie wiedziałem tylko o matplotlib.pyplot.imshow i musiałem wyciągnij wiele sztuczek, aby wyeliminować wszystkie dodatki z pliku obrazu i zapobiec jakiejkolwiek interpolacji / wygładzaniu itp. (i dlatego zwróciłem sięgnuplot
w pewnym momencie). Zeimsave
jest to dość łatwe, więc jestem z powrotem do korzystaniamatplotlib
z łatwym jeszcze wciąż elastyczny (pod względem colormap, skalowanie, itp) roztworu dla „piksel” dokładny działek. Oto przykład:źródło
OK, oto inne możliwe rozwiązanie (oddzieliłem je od mojego pierwszego niewygodnego podejścia). Tworzy fabułę natychmiast, mniej niż sekundę. Nie trzeba zmieniać nazwy ani tworzyć niepotrzebnego pliku.
Chyba kluczem jest użycie
term png
ips 0.1
.Nie mam dowodu, ale myślę, że
ps 1
byłoby ok. 6 pikseli dużych i tworzyłoby zachodzące na siebie i / lub białe piksele w rogu. Ponownie, z jakiegokolwiek powodu wydaje się, że działa,term png
ale nie działaterm pngcairo
.To, co przetestowałem (Win7, gnuplot 5.2.6), to plik binarny z
00 00 FF
powtarzającym się wzorem (nie mogę tutaj wyświetlić bajtów zerowych). Ponieważ gnuplot najwyraźniej odczytuje 4 bajty na element tablicy (format="%d"
), prowadzi to do naprzemiennego wzorca RGB, jeśli kreślęwith lc rgb var
.W ten sam sposób (mam nadzieję) możemy dowiedzieć się, jak czytać
format="%f"
i używać go wraz z paletą kolorów. Chyba właśnie tego szukasz, prawda? Dalsze wyniki testu, komentarze, ulepszenia i wyjaśnienia są mile widziane.Kod:
Wynik:
źródło