Sza*_*lcs 53 post wolfram-mathematica jlink imgur
这是对所有mathematica标记粉丝的挑战.让我们通过创建一个imgur上传器将图像插入到Mathematica的SO帖子中更加方便.
我们如何创建一个imgur[g_]将光栅化其参数的函数(确保最终大小不超过StackOverflow帖子的宽度),将其转换为PNG,将其上传到imgur,并返回准备粘贴的MarkDown行,如?
有用的参考:
我没有调整后一种方法来上传图像而不先将其导出到文件中.
警告,小心使用!StackOverflow使用单独的imgur安装,可以无限期地保留图像.如果你使用主要的imgur,如果没有人看到它们,图像将在6个月后消失.不幸的是,截至2011年11月,似乎没有正式的方式以编程方式将图像上传到StackOverflow.
更新: 请参阅下面的解决方案,直接上传到StackOverflow .
Arn*_*ing 16
一只小鸟刚刚告诉我这个问题的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]];
""
]
Run Code Online (Sandbox Code Playgroud)
这只是V8和XML导入选项"RequestMethod","RequestParameters"没有文档和实验(因此可能会有变化).
Sza*_*lcs 13
注意:在此处获取具有此功能的现成调色板.
Arnoud的解决方案让我兴奋和不耐烦,所以这里有一个改进.没有研究他的代码,我不可能做到这一点.这个版本似乎更可靠,更不容易出现超时错误,但说实话,我根本不懂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];
]
]
Run Code Online (Sandbox Code Playgroud)
更新:
这是一个按钮,将显示选择的预览,并将提供上传(或取消).它需要定义先前的功能.
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"]]]]
Run Code Online (Sandbox Code Playgroud)
不幸的是我无法将按钮放在palette(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]
Run Code Online (Sandbox Code Playgroud)
警告:即使您在预览框中单击取消,它也会破坏剪贴板内容.
Arn*_*ing 12
注意:这是使用我的匿名密钥匿名imgur上传器.imgur网站将上传限制为每小时上传50次,这应该是正常的,但如果很多人同时尝试这种情况,这可能会导致问题.所以请在这里获取您自己的匿名密钥:
http://imgur.com/register/api_anon
然后用自己的密钥替换下面代码中的密钥(谢谢!).
代码中最棘手的部分是从Mathematica表达式到PNG图像到Base64编码到URL编码的转换.大约有1000种方法可以做错,我想我设法尝试了所有这些方法.
代码分解为几个部分:
Hyperlink函数).这是代码:
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]];
""
]
Run Code Online (Sandbox Code Playgroud)
测试:
In[]:= g = Graphics[{Blue, Disk[]}, PlotRange -> 1.2, ImageSize -> Small];
pic = Overlay[{Blur[Binarize@g, 10], g}];
imgur[pic]
Out[]= 
Run Code Online (Sandbox Code Playgroud)
而实际形象:

| 归档时间: |
|
| 查看次数: |
3087 次 |
| 最近记录: |