【问题标题】:How to convert a JSON string to an image?如何将 JSON 字符串转换为图像?
【发布时间】:2013-05-14 19:07:12
【问题描述】:

我有一个将图像转换为 JSON 数组的应用程序,并将其保存到 blob 字段中:

function getImage(): String;
var
  memorystream : TMemoryStream;
  jsonArray    : TJSONArray;

begin
  memorystream := TMemoryStream.Create;
  myImage.Picture.Graphic.SaveToStream(memorystream);
  memorystream.Position := 0;

  jsonArray := TJSONArray.Create;
  jsonArray := TDBXJSONTools.StreamToJSON(memorystream, 0, memorystream.Size);

  memorystream.Free;

  Result := jsonArray.ToString;
end;

PNG图片的转换结果如下:

[137,80,78,71,13,10,26,10,0,0, ... ]

此结果存储在我使用此代码返回的 blob 字段中:

stream := TStream.Create;
stream := cdsPesquisa.CreateBlobStream(fieldAux, bmRead);
stream.Position := 0;

jsonArray := TJSONArray.Create;
jsonArray := TDBXJSONTools.StreamToJSON(stream, 0, stream.Size);

这里,我一开始有相同的JSON字符串[137,80,78,71,13,10,26,10,0,0, ... ],但是我需要再次将这个JSON数组转换成图像。

我怎样才能做到这一点?

【问题讨论】:

  • 存储为 json 字符串会大大增加存储需求。例如文本形式的137 是 3 个字节,v.s.如果您存储为原始 0x89 十六进制字节,则为 1 个字节。
  • 按理说,如果您使用TDBXJSONTools.StreamToJSON 转换为数组以输出,则需要使用TDBXJSONTools.JSONToStream 反转返回。但是,将其转换为 JSONArray 以将其存储到 TBlobField 然后再将其转换回来是没有意义的,因为您可以只保存原始数据而无需首先进行转换。
  • 好吧,我可以将其更改为发送 json 字符串,而不是使用十六进制发送字节,但这不是我的问题。我需要将此字符串发送到我的服务器。感谢回复
  • 感谢 Ken,但我只是第一次使用此转换,因为我需要将此字符串传递给 SQL,因为我不在线使用 clientdataset。
  • @Ken 如果看起来我偷了你的答案,对不起。我写了代码,完全错过了所有的 JSON。然后我看到你的评论说这是不必要的。

标签: json delphi delphi-xe2 datasnap


【解决方案1】:

按照 Ken 的建议,最简单的方法是忘记所有关于 JSON 的内容并直接写入 blob 字段。

保存

Stream := TMemoryStream.Create;
try
  myImage.Picture.Graphic.SaveToStream(Stream);
  Stream.Position := 0;
  fieldAux.LoadFromStream(Stream);
finally
  Stream.Free;
end;

加载中

Stream := TMemoryStream.Create;
try
  fieldAux.SaveToStream(Stream);
  Stream.Position := 0;
  myImage.Picture.Graphic.LoadFromStream(Stream);
finally
  Stream.Free;
end;

您在 cmets 中似乎坚持认为 JSON 是您所需要的。我觉得这有点难以置信。但无论如何,要将保存在字符串中的 JSON 数组转换为图像,请执行以下操作:

jsonArray := TJSONObject.ParseJSONValue(jsonString) as TJSONArray;
try
  Stream := TDBXJSONTools.JSONToStream(jsonArray);
  try
    Stream.Position := 0;
    myImage.Picture.Graphic.LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
finally
  jsonArray.Free;
end;

此外,据我所知,您调用 TDBXJSONTools.StreamToJSON 的代码不起作用。它产生一个空的 JSON 数组对象。


最后,您的代码像筛子一样泄漏。您误以为不需要释放您创建的对象。您还错误地实例化了对象,然后用不同的对象覆盖了新对象,从而泄漏了第一个对象。看看我是如何创建对象的,并与您的代码进行比较。例如:

jsonArray := TJSONArray.Create ;
jsonArray := TDBXJSONTools.StreamToJSON( memorystream , 0 , memorystream.Size ) ;

在这里实例化一个TJSONArray 对象并将对该对象的引用存储在jsonArray 中。释放该引用是您的工作。但是当你用StreamToJSON返回的新对象的引用覆盖它时,你会立即放弃下一行中的引用。由于您根本没有释放jsonArray,因此您泄漏的不是一个,而是两个对象。

您确实需要复习您对 Delphi 生命周期管理的基本了解。

【讨论】:

  • +1。我也不使用该类来处理 JSON(我实际上根本不使用 JSON),并且还没有开始实际编写代码来进行反转。你打败了我。 :-)
  • @David,只是一个挑剔,我不知道fieldAux 是什么,但大多数流实现在您调用LoadFromStream 时将流位置重置为0。
  • @TLama fieldAuxTBlobField
  • @TLama 那么对于 blob 字段,不需要将位置设置为零?
  • @David,在大多数 LoadFromStream 实现中。例如TBlobField.LoadFromStream 调用祖先的TStream.CopyFrom 将输入流位置重置为0(至少在Delphi 2009 中)[至少现在;我肯定也将其重置为 0]。
猜你喜欢
  • 1970-01-01
  • 2017-03-22
  • 2014-12-17
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多