Prześlij zdjęcia do Imgur z Mathematica
Oto wyzwanie dla wszystkich mathematica
obserwujących tag. Uczyńmy to o wiele wygodniejsze wstawianie obrazów do posta z Mathematica, tworząc Imgur uploader.
Jak możemy utworzyć funkcję imgur[g_]
, która będzie rasteryzować swój argument (upewniając się, że ostateczny rozmiar nie jest szerszy niż szerokość postów Stoskoverflow), przekonwertować go do PNG, przesłać do imgur i zwrócić gotowy do wklejenia MarkDown wiersz, taki jak ![Mathematica graphic](http://i.imgur.com/ZENa4.jpg)
?
Przydatne Bibliografia:
- Imgur API
- W przeciwieństwie do innych programów, które nie są w pełni kompatybilne z komputerem, nie są w pełni kompatybilne z komputerem.]}
- przykład użycia żądań POST z Mathematica NA SO (uploading to ifile.it)
Nie udało mi się dostosować tej ostatniej metody do przesyłania obrazu bez uprzedniego eksportowania go do pliku.
Uwaga, używaj ostrożnie! StackOverflow używa oddzielnego imgur instalacja , która przechowuje obrazy w nieskończoność. Jeśli użyjesz głównego imgur, obrazy znikną po 6 miesiącach, jeśli nikt ich nie obejrzy. Niestety od listopada 2011 roku wydaje się, że nie ma oficjalnego sposobu , aby programowo przesyłać obrazy do StackOverflow.
Aktualizacja: zobacz poniżej rozwiązanie do bezpośredniego przesyłania do StackOverflow .
3 answers
Mały ptaszek właśnie poinformował mnie o Mathematica rozwiązanie tego pytania (podstawowa implementacja nadal używa Jlinka, ale ta odpowiedź ukrywa cały kod związany z Javą):
imgur[expr_] := Module[
{url, key, image, data, xml, imgurUrl},
url = "http://api.imgur.com/2/upload";
key = "c07bc3fb59ef878d5e23a0c4972fbb29";
image = Fold[ExportString, expr, {"PNG", "Base64"}];
xml = Import[url,
"XML", "RequestMethod" -> "POST",
"RequestParameters" -> {"key" -> key, "image" -> image}];
imgurUrl = Cases[xml, XMLElement["original", {}, {string_}] :> string,
Infinity][[1]];
"![Mathematica graphic](" <> imgurUrl <> ")"
]
Jest to tylko Wersja V8, a Opcje importu XML
"RequestMethod"
i "RequestParameters"
są nieudokumentowane i eksperymentalne (i dlatego mogą ulec zmianie).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-01 17:32:59
Uwaga: Pobierz gotową paletę z tą funkcjonalnością tutaj .
Rozwiązanie Arnouda mnie podnieciło i zniecierpliwiło, więc oto ulepszenie. Nie zrobiłbym tego bez przestudiowania jego kodu. Ta wersja wydaje się być nieco bardziej niezawodna i mniej podatna na błędy timeoutu, ale szczerze mówiąc, nie znam w ogóle Javy, więc wszelkie ulepszenia są mile widziane.
Najważniejsze: ta wersja ładuje się bezpośrednio do stack.imgur.com
, więc jest bezpiecznie używać tutaj w StackOverflow, bez obawy, że przesłane zdjęcia znikną po pewnym czasie.
Udostępniam trzy funkcje:
-
stackImage
przesyła wyrażenie wyeksportowane jako PNG i zwraca adres URL -
stackMarkdown
zwraca markdown, gotowy do skopiowania -
stackCopyMarkdown
kopiuje markdown do schowka
Następny krok: Utwórz przycisk palety, który zrobi to automatycznie dla wybranej grafiki w notatniku. Ulepszenia w kodzie są bardzo Witam.
Needs["JLink`"]
stackImage::httperr = "Server returned respose code: `1`";
stackImage::err = "Server returner error: `1`";
stackImage[g_] :=
Module[
{getVal, url, client, method, data, partSource, part, entity, code,
response, error, result},
(* this function attempts to parse the response fro the SO server *)
getVal[res_, key_String] :=
With[{k = "var " <> key <> " = "},
StringTrim[
First@StringCases[First@Select[res, StringMatchQ[#, k ~~ ___] &],
k ~~ v___ ~~ ";" :> v],
"'"]
];
data = ExportString[g, "PNG"];
JavaBlock[
url = "https://stackoverflow.com/upload/image";
client = JavaNew["org.apache.commons.httpclient.HttpClient"];
method = JavaNew["org.apache.commons.httpclient.methods.PostMethod", url];
partSource = JavaNew["org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource", "mmagraphics.png", MakeJavaObject[data]@toCharArray[]];
part = JavaNew["org.apache.commons.httpclient.methods.multipart.FilePart", "name", partSource];
part@setContentType["image/png"];
entity = JavaNew["org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity", {part}, method@getParams[]];
method@setRequestEntity[entity];
code = client@executeMethod[method];
response = method@getResponseBodyAsString[];
]
If[code =!= 200, Message[stackImage::httperr, code]; Return[$Failed]];
response = StringTrim /@ StringSplit[response, "\n"];
error = getVal[response, "error"];
result = getVal[response, "result"];
If[StringMatchQ[result, "http*"],
result,
Message[stackImage::err, error]; $Failed]
]
stackMarkdown[g_] := "![Mathematica graphics](" <> stackImage[g] <> ")"
stackCopyMarkdown[g_] := Module[{nb, markdown},
markdown = Check[stackMarkdown[g], $Failed];
If[markdown =!= $Failed,
nb = NotebookCreate[Visible -> False];
NotebookWrite[nb, Cell[markdown, "Text"]];
SelectionMove[nb, All, Notebook];
FrontEndTokenExecute[nb, "Copy"];
NotebookClose[nb];
]
]
Update:
Oto przycisk, który wyświetli podgląd wyboru i zaoferuje przesłanie (lub anulowanie). Wymaga zdefiniowania poprzednich funkcji.
Button["Upload to SO",
Module[{cell = NotebookRead@InputNotebook[], img},
If[cell =!= {}, img = Rasterize[cell];
MessageDialog[
Column[{"Upload image to StackExchange sites?",
img}], {"Upload and copy MarkDown" :> stackCopyMarkdown[img],
"Cancel" :> Null}, WindowTitle -> "Upload to StackExchange"]]]]
Niestety nie mogę umieścić przycisku w palecie (CreatePalette
), ponieważ wymiary palety będą miały wpływ na rasteryzację. Rozwiązania tego problemu są mile widziane.
Aktualizacja 2:
Na podstawie odpowiedzi na to pytanie , oto działający przycisk palety tylko dla systemu Windows:
button = Button["Upload to SO",
Module[{sel},
FrontEndExecute[
FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial", "MGF"]];
sel = Cases[NotebookGet@ClipboardNotebook[],
RasterBox[data_, ___] :>
Image[data, "Byte", ColorSpace -> "RGB", Magnification -> 1],
Infinity];
If[sel =!= {},
With[{img = First[sel]},
MessageDialog[
Column[{"Upload image to StackExchange sites?",
img}], {"Upload and copy MarkDown" :> stackCopyMarkdown[img],
"Cancel" :> Null}, WindowTitle -> "Upload to StackExchange"]
]
]
]
]
CreatePalette[button]
Ostrzeżenie: niszczy zawartość schowka, nawet jeśli klikniesz Anuluj w oknie podglądu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:45
Uwaga: to jest za pomocą anonimowego Imgur uploader z moim anonimowym kluczem. Witryna imgur ogranicza przesyłanie do 50 przesyłek / godzinę, co powinno być normalne, ale może to spowodować problem, jeśli Wiele osób spróbuje tego jednocześnie. Więc proszę, Zdobądź swój własny anonimowy klucz tutaj:
Http://imgur.com/register/api_anon
A następnie zastąp klucz w poniższym kodzie własnym kluczem (dzięki!).
Najtrudniejszą częścią kodu była konwersja od wyrażenia Mathematica do obrazu PNG do kodowania Base64 do kodowania URL. Istnieje około 1000 sposobów, aby zrobić to źle i myślę, że udało mi się wypróbować je wszystkie.
Kod dzieli się na kilka części:
- Zbuduj adres URL postu
- wykonaj połączenie HTTP
- Wyślij adres URL posta
- odczytaj wynik, czyli XML W tym celu należy pobrać plik imgur z pliku XML.]}
- sformatuj adres URL imgur jako markdown (lub jako Mathematica
Hyperlink
funkcja).
Oto kod:
imgur[expr_] :=
Module[{url, key, image, data, jUrl, jConn, jWriter, jInput, buffer,
byte, xml, imgurUrl},
Needs["JLink`"];
JLink`JavaBlock[
JLink`LoadJavaClass["java.net.URLEncoder"];
url = "http://api.imgur.com/2/upload";
key = "c07bc3fb59ef878d5e23a0c4972fbb29";
image = ExportString[ExportString[expr, "PNG"], "Base64"];
data =
URLEncoder`encode["key" , "UTF-8"] <> "=" <>
URLEncoder`encode[ key , "UTF-8"] <> "&" <>
URLEncoder`encode["image" , "UTF-8"] <> "=" <>
URLEncoder`encode[ image , "UTF-8"] ;
jUrl = JLink`JavaNew["java.net.URL", url];
jConn = jUrl@openConnection[];
jConn@setDoOutput[True];
jWriter =
JLink`JavaNew["java.io.OutputStreamWriter",
jConn@getOutputStream[]];
jWriter@write[data];
jWriter@flush[];
jInput = jConn@getInputStream[];
buffer = {};
While[(byte = jInput@read[]; byte >= 0), AppendTo[buffer, byte]];
];
xml = ImportString[FromCharacterCode[buffer], "XML"];
imgurUrl =
Cases[xml,
XMLElement["original", {}, {string_}] :>
string, \[Infinity]][[1]];
"![Mathematica graphic](" <> imgurUrl <> ")"
]
Testowanie:
In[]:= g = Graphics[{Blue, Disk[]}, PlotRange -> 1.2, ImageSize -> Small];
pic = Overlay[{Blur[Binarize@g, 10], g}];
imgur[pic]
Out[]= ![Mathematica graphic](http://i.imgur.com/eGOlL.png)
I rzeczywisty obraz:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-01 04:34:43