Загрузка изображений в Imgur из Mathematica
вот вызов для всех mathematica последователей теге. Давайте сделаем его намного удобнее вставлять изображения в SO post из Mathematica, создав imgur загрузчика.
как мы можем создать функцию imgur[g_] это растеризует его аргумент (убедившись, что конечный размер не шире ширины сообщений StackOverflow), преобразует его в PNG, загружает его в imgur и возвращает готовый к вставке MarkDown строку  ?
Полезные ссылки:
- API для карт
пример использования запроса POST от Mathematica в блоге WRI (публикация в Twitter) by ragfield
- пример использования запросов POST от Mathematica на SO (загрузка в ifile.it)
мне не удалось адаптировать этот последний метод для загрузки изображения без экспорта его в файл первый.
внимание, используйте с осторожностью! StackOverflow использует отдельная установка imgur, которые держат образы бесконечно. Если вы используете основной imgur,изображения исчезнут через 6 месяцев, если их никто не будет просматривать. К сожалению, по состоянию на ноябрь 2011 года там, кажется,нет официального пути для загрузки изображений в StackOverflow программно.
обновление:см. ниже решение для загрузки в StackOverflow напрямую.
3 ответов:
маленькая птичка только что сообщила мне о Mathematica решение этого вопроса (базовая реализация по-прежнему использует JLink, но этот ответ скрывает весь код, связанный с java):
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]]; "" ]это только V8 и
XMLпараметры импорта"RequestMethod"и"RequestParameters"являются недокументированными и экспериментальными (и поэтому могут быть изменены).
Примечание: получить готовую палитру с этой функциональностью здесь.
решение Арноуд меня взволновало и нетерпеливо, так что вот улучшение к нему. Я не смог бы сделать это, не изучив его код. Эта версия кажется несколько более надежной и менее подверженной ошибкам тайм-аута, но, честно говоря, я вообще не знаю Java, поэтому любые улучшения приветствуются.
самое главное: эта версия загружается в
stack.imgur.comнепосредственно, так что это безопасно использовать здесь на StackOverflow, не беспокоясь, что загруженные изображения исчезнут через некоторое время.Я предоставляю три функции:
stackImageзагружает выражение, экспортируется как PNG, и возвращает URLstackMarkdownвозвращает уценку, готовую к копированиюstackCopyMarkdownкопирует уценку в буфер обменаследующий шаг: создать кнопку палитры, которая делает это автоматически для выбранного графика в записной книжке. Улучшения в коде очень приветствуются.
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_] := "" 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]; ] ]обновление:
вот кнопка, которая покажет предварительный просмотр выбора и предложит загрузку (или отмену). Для этого необходимо определить предыдущие функции.
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"]]]]к сожалению я не могу поставить кнопку в палитре (
CreatePalette) потому что размеры палитры будут влиять на растеризацию. Решения этой проблемы будем приветствовать.обновление 2:
на основе ответа на этот вопрос, вот рабочая кнопка палитры только для 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]предупреждение: это разрушает содержимое буфера обмена, даже если вы нажмете кнопку Отмена в окне предварительного просмотра.
Примечание: это использование анонимного загрузчика imgur с моим анонимным ключом. Сайт imgur ограничивает загрузку до 50 загрузок / час, что должно быть нормально, но это может вызвать проблему, если многие люди пытаются это одновременно. Поэтому, пожалуйста, получите свой собственный анонимный ключ здесь:
http://imgur.com/register/api_anon
а затем заменить ключ в коде ниже с вашим собственным ключом (спасибо!).
В самой сложной частью кода было преобразование из выражения Mathematica в PNG-изображение в кодировку Base64 в кодировку URL. Есть около 1000 способов сделать это неправильно, и я думаю, что мне удалось попробовать их все.
код разбивается на несколько частей:
- построить url сообщения
- сделать HTTP-соединение
- Отправить сообщение url
- прочитайте назад результат, который XML
- извлечение url imgur из XML
в в imgur URL-адрес в качестве уценки (или как Mathematica
Comments