1

我想知道是否有人可以建议。我编写了一个 .NET 4 WCF 服务,该服务旨在为扫描的文档提供服务,并且正在努力让 Delphi 7 消费者工作。

在 .NET 方面,我使用以下代码将图像转换为位图,然后转换为字节数组:

        using (Bitmap img = new Bitmap(fileName))
        {
            ImageConverter converter = new ImageConverter();
            _bytes = (byte[])converter.ConvertTo(img, typeof(byte[]));
        }

在消费者方面,我想将 ByteArray 读入 TImage.Picture ,这就是计划失败的地方。“LoadFromStream”行中的以下代码错误

带有消息“位图图像无效”的 EInvalidGraphic

procedure TBarcodeImageForm.FetchFile;
var
  bytes : TByteDynArray;
  info  : TDocInfo;
  Stream : TMemoryStream;
  bmp : TBitMap;
begin
  info := TDocInfo(FDocList.Items[lbFIles.ItemIndex]);
  bytes := FDocButton.FetchDocument(info.FilePath).Data;
  stream := TMemoryStream.Create();
  try
    Stream.Write(bytes[0], Length(Bytes));
    Stream.Position := 0;
    bmp := TBitMap.Create;
    bmp.LoadFromStream(stream);
  finally
    Stream.Free;
  end; 
end;

通过使用 TFileStream 代替上面的内存流,我已经证明数据是有效的——也就是说,我可以在 MSPaint 中加载结果。我不得不承认我被困在下一步:Delphi 7 是否过于过时而无法处理现代位图?服务器端的文件与 tiffs 和 jpgs 相关吗?接下来我该怎么办?

感激地收到任何建议。

更新 - - - - - - - - - -

我更改了代码,以便传递 JPG,结果非常相似。这次我在尝试加载图像客户端时收到 JPEG 错误 #53。如果我使用 TFileStream 并保存到磁盘,则生成的文件在 Windows 图片查看器中看起来不错,但仍不会加载到 TImage 组件中。

客户端现在看起来像这样

  stream := TFileStream.Create('c:\temp.jpg', fmCreate);
  try
    Stream.Write(bytes[0], Length(Bytes));
    Stream.Position := 0;
  finally
    Stream.Free;
  end;

  try
    imgDocument.Picture.LoadFromFile('c:\temp.jpg');
  except end;

服务器端(这次发布整个数据合约以防万一)

    [DataContract]
public class ImageData
{
    private byte[] _bytes;

    [DataMember]
    public byte[] Data
    {
        get { return _bytes; }
        set { _bytes = value; }
    }

    public ImageData(string fileName)
    {
        using (MemoryStream memStream = new MemoryStream())
        {
            using (Image img = Image.FromFile(fileName))
            {
                img.Save(memStream, ImageFormat.Jpeg);
            }
            _bytes = new Byte[memStream.Length];
            int i = 0;
            while (i < memStream.Length)
                i += memStream.Read(_bytes, i, 128000);
        }
    }
}

更新 - - - - - - - - - - - - - - - - - - - - - - - - - ----------------

Winforms 使用者对服务的成功测试使用了以下代码。

if (docList != null)
{
    using (MemoryStream memStream = 
        new MemoryStream(client.FetchDocument(docList.Items[0].FilePath).Data))
    {
        System.Drawing.Image img = Image.FromStream(memStream); 
        pictureBox1.Image = img; 
    }
}   
4

3 回答 3

1

我的印象是您让 WCF 负责在服务器和客户端之间编组和序列化数据的过程(两者都是由工具为您自动生成的?)并且您对“在线”格式,现在您想在 Delphi 7 中编写一个可以读取此格式的客户端。

我会警告您,您将面临一场艰苦的斗争,但是如果您的 WCF 使用 SOAP 消息,那么您就有机会在 Delphi 中编写一个使用 WCF 服务消息的 SOAP 客户端。

至于图像本身,我不知道它们是如何序列化的。但是一旦你发现它应该很容易。假设 WCF 不是简单地序列化 System.Drawing.Bitmap 而是在磁盘上传输 Bitmap 文件的原始字节,那么您就一切就绪:只需将 WCF 消息的字节转储到磁盘或内存缓冲区并打开他们用 TBitmap。

于 2012-08-11T01:31:03.947 回答
1

对不起,大家 - 这原来是一个红鲱鱼。问题是我提供的图像首先是无效的。只需快速致电第三方供应商即可。

从好的方面来说,这意味着我提供的代码示例基本上是合理的。

于 2012-08-16T17:40:57.690 回答
1

除非您同意使用位图图像,否则您可能想尝试通过 TJPegImage(在 JPeg 单元之外)从流中读取图像。我正在做类似于您正在尝试的事情,但是通过 AtoZed 的“CrossTalk”产品直接从 .Net 4 包装器中获取图像字节。

因此,首先我必须将跨边界传递的 .Net MemoryStream 对象转换为 Delphi 字节数组。然后我将它加载到 Delphi TMemoryStream 中并将其带入 TJpegImage。

(我最初遇到了与您相同的问题,直到我决定 LoadfromFile 显然是根据文件名定制加载方式。基于此,我明确地为 JPegs、Tiffs 等创建了正确的图像变体,而不是尝试将其作为通用 TImage 加载。)

当返回的图像是 Jpeg 时,这适用于 Delphi7:

  dJpegImage: TJpegImage;
  imageMemoryStream: MemoryStream;
  pictureBoxImageOutput: TImage;
  lengthImageByteArray: Integer;   // already set before this fragment based on the .Net Image info
  imageDelphiByteArray: array of byte;
  ...
  ...
  imageStream := TMemoryStream.Create();
  imageStream.WriteBuffer(imageDelphiByteArray[0], lengthImageByteArray);
  imageStream.Position := 0;
  dJpegImage := TJPEGImage.Create;
  dJpegImage.LoadFromStream(imageStream);
  pictureBoxImageOutput.Picture.Graphic := dJpegImage;
于 2012-08-17T18:09:53.640 回答