Image resizing script is not returning a proper stream for further handling

梦想与她 提交于 2020-01-17 05:06:26

问题


Current project:

  • ASP.NET 4.5.2
  • MVC 5

I am trying to leverage the TinyPNG API, and if I just pipe the image over to it, it works great. However, since the majority of users will be on a mobile device, and these produce images at a far higher resolution than what is needed, I am hoping to reduce the resolution of these files prior to them being piped over to TinyPNG. It is my hope that these resized images will be considerably smaller than the originals, allowing me to conduct a faster round trip.

My code:

public static async Task<byte[]> TinyPng(Stream input, int aspect) {
  using(Stream output = new MemoryStream())
  using(var png = new TinyPngClient("kxR5d49mYik37CISWkJlC6YQjFMcUZI0")) {
    ResizeImage(input, output, aspect, aspect); // Problem area
    var result = await png.Compress(output);
    using(var reader = new BinaryReader(await (await png.Download(result)).GetImageStreamData())) {
      return reader.ReadBytes(result.Output.Size);
    }
  }
}
public static void ResizeImage(Stream input, Stream output, int newWidth, int maxHeight) {
  using(var srcImage = Image.FromStream(input)) {
    var newHeight = srcImage.Height * newWidth / srcImage.Width;
    if(newHeight > maxHeight) {
      newWidth = srcImage.Width * maxHeight / srcImage.Height;
      newHeight = maxHeight;
    }

    using(var newImage = new Bitmap(newWidth, newHeight))
    using(var gr = Graphics.FromImage(newImage)) {
      gr.SmoothingMode = SmoothingMode.AntiAlias;
      gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
      gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
      gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
      newImage.Save(output, ImageFormat.Jpeg);
    }
  }
}

So the ResizeArea is supposed to accept a stream and output a stream, meaning that the TinyPNG .Compress() should work just as well with the output as it would with the original input. Unfortunately, only the .Compress(input) works -- with .Compress(output) TinyPNG throws back an error:

400 - Bad Request. InputMissing, File is empty

I know TinyPNG has its own resizing routines, but I want to do this before the image is sent out over the wire to TinyPNG so that file size (and therefore transmission time) is reduced as much as possible prior to the actual TinyPNG compression.


回答1:


…Aaaaand I just solved my problem by using another tool entirely.

I found ImageProcessor. Documentation is a royal b**ch to get at because it only comes in a Windows *.chm help file (it’s not online… cue one epic Whisky. Tango. Foxtrot.), but after looking at a few examples it did solve my issue quite nicely:

public static async Task<byte[]> TinyPng(Stream input, int aspect) {
  using(var output = new MemoryStream())
  using(var png = new TinyPngClient("kxR5d49mYik37CISWkJlC6YQjFMcUZI0")) {
    using(var imageFactory = new ImageFactory()) {
      imageFactory.Load(input).Resize(new Size(aspect, 0)).Save(output);
    }
    var result = await png.Compress(output);
    using(var reader = new BinaryReader(await (await png.Download(result)).GetImageStreamData())) {
      return reader.ReadBytes(result.Output.Size);
    }
  }
}

and everything is working fine now. Uploads are much faster now as I am not piping a full-sized image straight through to TinyPNG, and since I am storing both final-“full”-sized images as well as thumbnails straight into the database, I am now not piping the whole bloody image twice.

Posted so that other wheel-reinventing chuckleheads like me will actually have something to go on.



来源:https://stackoverflow.com/questions/40368651/image-resizing-script-is-not-returning-a-proper-stream-for-further-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!