将图像从Mathematica上传到Imgur

这是对所有mathematica标签追随者的挑战。 让我们通过创build一个imgur上传器,将图像插入到Mathematica的SOpost中更加方便。

我们如何创build一个函数imgur[g_]来对其参数进行栅格化(确保最终的大小不会超过StackOverflow文章的宽度),将其转换为PNG,将其上传到imgur,并返回一个准备好粘贴MarkDown行如![Mathematica graphic](http://i.imgur.com/ZENa4.jpg)

有用的参考:

  • Imgur API
  • 使用 ragfield 在WRI博客上使用Mathematica的POST请求(发布到Twitter)的示例
  • 在SO上使用来自Mathematica的POST请求的示例(上传到ifile.it)

我没有适应这后一种方法来上传图像,而不是先导出到文件。


警告,小心使用! StackOverflow使用独立的imgur安装 ,无限期地保留图像。 如果您使用主视图, 如果没有人查看它们 , 图像将在6个月后消失 。 不幸的是截至2011年11月,似乎没有官方的方式上传图像到StackOverflow编程。


更新: 请参阅下面的解决scheme, 直接上传到StackOverflow。

一个小鸟刚刚告诉我这个问题的一个Mathematica解决scheme(底层实现仍然使用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]]; "![Mathematica graphic](" <> imgurUrl <> ")" ] 

这只是V8, XML导入选项"RequestMethod""RequestParameters"是没有logging和实验的(因此可能会有变化)。

注意: 在这里使用这个function获得一个现成的调色板。


阿诺德的解决scheme让我兴奋和不耐烦,所以这是一个改进。 如果不研究他的代码,我无法做到这一点。 这个版本似乎更可靠,不太容易出现超时错误,但说实话,我根本不知道Java,所以任何改进都是值得欢迎的。

最重要的是:这个版本直接上传到stack.imgur.com ,所以在StackOverflow上使用这个版本是安全的,不用担心上传的图片会在一段时间后消失。

我提供了三个function:

  • stackImage上传expression式,导出为PNG,并返回URL
  • stackMarkdown返回降价,准备复制
  • stackCopyMarkdown将降价复制到剪贴板

下一步:创build一个调色板button,为笔记本中的选定graphics自动执行此操作。 代码的改进是非常受欢迎的。


 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]; ] ] 

更新:

这里有一个button,将显示select的预览,并将提供上传(或取消)。 它要求定义以前的function。

 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"]]]] 

不幸的是,我不能把button放在调色板( CreatePalette )中,因为调色板尺寸会影响光栅化。 解决这个问题是值得欢迎的。

更新2:

基于这个问题的答案,这里有一个可用的Windows调色板button:

 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

然后用自己的密钥replace下面代码中的密钥( 谢谢! )。

编码最棘手的部分是从Mathematicaexpression式到PNG图像到Base64编码到URL编码的转换。 有大约1000种方式做错了,我想我设法尝试所有。

代码分解成几个部分:

  • 构buildPOSTurl
  • build立HTTP连接
  • 发送POSTurl
  • 回读结果,即XML
  • 从XML中提取imgur url
  • 将imgur url格式化为markdown(或作为Mathematica Hyperlinkfunction)。

这里是代码:

 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 <> ")" ] 

testing:

 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) 

而实际的形象:

Mathematica图形

Interesting Posts