LEADTOOLS Support
General
General Questions
How to use Raster Service without creating a temporary file?
#1
Posted
:
Wednesday, May 10, 2017 1:17:36 PM(UTC)
Groups: Registered
Posts: 20
I'm looking at the following location and I'm looking at the Load method from C:\LEADTOOLS 19\Examples\REST\Leadtools.RESTServices\Raster\Raster.cs.
I've made a Load method similar to this method called LoadFromData but I've modified it to take in Base64 encoded image data instead of a URL.
Here is the original code that I have copied from:
Code:
public Stream Load(string uri, int pageNumber, int resolution, string mimeType, int bitsPerPixel, int qualityFactor, int width, int height)
{
// uri is not optional
if (string.IsNullOrEmpty(uri))
throw new ArgumentNullException("uri");
if (pageNumber < 0)
throw new ArgumentException("'pageNumber' must be a value greater than or equals to 0");
// Default is page 1
if (pageNumber == 0)
pageNumber = 1;
if (resolution < 0)
throw new ArgumentException("'resolution' must be a value greater than or equals to 0");
// Sanity check on other parameters
if (qualityFactor < 0 || qualityFactor > 100)
throw new ArgumentException("'qualityFactor' must be a value between 0 and 100");
if (width < 0 || height < 0)
throw new ArgumentException("'width' and 'height' must be value greater than or equal to 0");
// Get the image format
SaveImageFormat saveFormat = SaveImageFormat.GetFromMimeType(mimeType);
// Use a temp file, much faster than calling Load/Info from a URI directly
// In a production service, you might want to create a caching mechanism
string tempFile = Path.GetTempFileName();
try
{
// Force the uri to be fully qualified, reject everything else for security reasons
Uri fullyQualifiedUri = new Uri(uri, UriKind.Absolute);
if (fullyQualifiedUri.IsFile || fullyQualifiedUri.IsUnc)
throw new Exception("URL cannot be local file or UNC path.");
// Download the file
using (WebClient client = new WebClient())
client.DownloadFile(fullyQualifiedUri, tempFile);
using (RasterCodecs codecs = new RasterCodecs())
{
ServiceHelper.InitCodecs(codecs, resolution);
// Load the page
using (RasterImage image = codecs.Load(tempFile, 0, CodecsLoadByteOrder.BgrOrGray, pageNumber, pageNumber))
{
// Resize it (will only resize if both width and height are not 0), will also take care of FAX images (with different resolution)
ImageResizer.ResizeImage(image, width, height);
// We need to find out the format, bits/pixel and quality factor
// If the user gave as a format, use it
if (saveFormat == null)
{
// If the user did not give us a format, use PNG
saveFormat = new PngImageFormat();
mimeType = "image/png";
}
saveFormat.PrepareToSave(codecs, image, bitsPerPixel, qualityFactor);
// Save it to a memory stream
MemoryStream ms = new MemoryStream();
codecs.Save(image, ms, saveFormat.ImageFormat, saveFormat.BitsPerPixel);
ms.Position = 0;
// Set the MIME type and Content-Type if there is a valid web context
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
currentContext.OutgoingResponse.ContentType = mimeType;
currentContext.OutgoingResponse.ContentLength = ms.Length;
}
return ms;
}
}
}
catch (Exception ex)
{
Log(string.Format("Load - Error:{1}{0}TempFile:{2}{0}Uri:{3}, PageNumber:{4}", Environment.NewLine, ex.Message, tempFile, uri, pageNumber));
throw ex;
}
finally
{
if (File.Exists(tempFile))
{
try
{
File.Delete(tempFile);
}
catch { }
}
}
}
Here is my code:
Code:
public Stream LoadFromData(Stream streamData, int pageNumber, int resolution, string mimeType, int bitsPerPixel, int qualityFactor, int width, int height)
{
// document data is not optional
StreamReader reader = new StreamReader(streamData);
string docData = reader.ReadToEnd();
reader.Close();
reader.Dispose();
if (string.IsNullOrEmpty(docData))
throw new ArgumentNullException("Document Data");
if (pageNumber < 0)
throw new ArgumentException("'pageNumber' must be a value greater than or equals to 0");
// Default is page 1
if (pageNumber == 0)
pageNumber = 1;
if (resolution < 0)
throw new ArgumentException("'resolution' must be a value greater than or equals to 0");
// Sanity check on other parameters
if (qualityFactor < 0 || qualityFactor > 100)
throw new ArgumentException("'qualityFactor' must be a value between 0 and 100");
if (width < 0 || height < 0)
throw new ArgumentException("'width' and 'height' must be value greater than or equal to 0");
// Get the image format
SaveImageFormat saveFormat = SaveImageFormat.GetFromMimeType(mimeType);
// Use a temp file, much faster than calling Load/Info from a URI directly
// In a production service, you might want to create a caching mechanism
string tempFile = Path.GetTempFileName();
try
{
// Create the file
File.WriteAllBytes(tempFile, Convert.FromBase64String(docData));
using (RasterCodecs codecs = new RasterCodecs())
{
ServiceHelper.InitCodecs(codecs, resolution);
// Load the page
using (RasterImage image = codecs.Load(tempFile, 0, CodecsLoadByteOrder.BgrOrGray, pageNumber, pageNumber))
{
// Resize it (will only resize if both width and height are not 0), will also take care of FAX images (with different resolution)
ImageResizer.ResizeImage(image, width, height);
// We need to find out the format, bits/pixel and quality factor
// If the user gave as a format, use it
if (saveFormat == null)
{
// If the user did not give us a format, use PNG
saveFormat = new PngImageFormat();
mimeType = "image/png";
}
saveFormat.PrepareToSave(codecs, image, bitsPerPixel, qualityFactor);
// Save it to a memory stream
MemoryStream ms = new MemoryStream();
codecs.Save(image, ms, saveFormat.ImageFormat, saveFormat.BitsPerPixel);
ms.Position = 0;
// Set the MIME type and Content-Type if there is a valid web context
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
currentContext.OutgoingResponse.ContentType = mimeType;
currentContext.OutgoingResponse.ContentLength = ms.Length;
}
return ms;
}
}
}
catch (Exception ex)
{
Log(string.Format("LoadFromData - Error:{1}{0} PageNumber:{2}", Environment.NewLine, ex.Message, pageNumber));
throw ex;
}
finally
{
if (File.Exists(tempFile))
{
try
{
File.Delete(tempFile);
}
catch { }
}
}
}
This code works, it gives me back a MemoryStream object similar to the original Load method that I can display as an image to the user.
However, I want to modify this code further to not use any temporary files. I've noticed that the codecs.Load() method is currently taking the path to the file but this method can also take a Stream object. I've tried using two different Stream objects for this method:
FileStream: I got file Stream to work as expected with no problems. However, using this Stream object still makes me use a temporary file to write my data to.
MemoryStream: This is the Stream object that I would like to use because I can simply write data to it without the use of a temporary file. However, I haven't gotten this Stream to work. When I use this Stream and call the method, I get back the following response from the server: {"Detail":null,"FaultType":"RasterException","Message":"Invalid file format"}
Here is my code that uses the MemoryStream instead of a temporary file:
Code:
public Stream LoadFromData(Stream streamData, int pageNumber, int resolution, string mimeType, int bitsPerPixel, int qualityFactor, int width, int height)
{
// document data is not optional
StreamReader reader = new StreamReader(streamData);
string docData = reader.ReadToEnd();
reader.Close();
reader.Dispose();
if (string.IsNullOrEmpty(docData))
throw new ArgumentNullException("Document Data");
if (pageNumber < 0)
throw new ArgumentException("'pageNumber' must be a value greater than or equals to 0");
// Default is page 1
if (pageNumber == 0)
pageNumber = 1;
if (resolution < 0)
throw new ArgumentException("'resolution' must be a value greater than or equals to 0");
// Sanity check on other parameters
if (qualityFactor < 0 || qualityFactor > 100)
throw new ArgumentException("'qualityFactor' must be a value between 0 and 100");
if (width < 0 || height < 0)
throw new ArgumentException("'width' and 'height' must be value greater than or equal to 0");
// Get the image format
SaveImageFormat saveFormat = SaveImageFormat.GetFromMimeType(mimeType);
// Use a temp file, much faster than calling Load/Info from a URI directly
// In a production service, you might want to create a caching mechanism
//string tempFile = Path.GetTempFileName();
try
{
// Download the file
MemoryStream docStream = new MemoryStream();
StreamWriter writer = new StreamWriter(docStream);
writer.Write(Convert.FromBase64String(docData));
writer.Flush();
docStream.Position = 0;
using (RasterCodecs codecs = new RasterCodecs())
{
ServiceHelper.InitCodecs(codecs, resolution);
// Load the page
using (RasterImage image = codecs.Load(docStream, 0, CodecsLoadByteOrder.BgrOrGray, pageNumber, pageNumber))
{
// Resize it (will only resize if both width and height are not 0), will also take care of FAX images (with different resolution)
ImageResizer.ResizeImage(image, width, height);
// We need to find out the format, bits/pixel and quality factor
// If the user gave as a format, use it
if (saveFormat == null)
{
// If the user did not give us a format, use PNG
saveFormat = new PngImageFormat();
mimeType = "image/png";
}
saveFormat.PrepareToSave(codecs, image, bitsPerPixel, qualityFactor);
// Save it to a memory stream
MemoryStream ms = new MemoryStream();
codecs.Save(image, ms, saveFormat.ImageFormat, saveFormat.BitsPerPixel);
ms.Position = 0;
// Set the MIME type and Content-Type if there is a valid web context
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
currentContext.OutgoingResponse.ContentType = mimeType;
currentContext.OutgoingResponse.ContentLength = ms.Length;
}
return ms;
}
}
}
catch (Exception ex)
{
Log(string.Format("LoadFromData - Error:{1}{0} PageNumber:{2}", Environment.NewLine, ex.Message, pageNumber));
throw ex;
}
}
I'm guessing it gives an Invalid File Format error because I'm not actually reading from a file.
In the original code, it mentions next to the creation of the temporary file "In a production service, you might want to create a caching mechanism". What is this referring to? Is it possible to write my code that doesn't use a temporary file? Is there a different Stream besides a FileStream that I can use?
Thanks for any help.
Edited by moderator Friday, May 12, 2017 9:55:12 PM(UTC)
| Reason: Not specified
#2
Posted
:
Monday, May 15, 2017 3:56:22 PM(UTC)
Groups: Manager, Tech Support, Administrators
Posts: 218
Was thanked: 12 time(s) in 12 post(s)
Hello,
Thank you for posting your question on the LEADTOOLS Technical Support Forums.
It seems that you issues is related to the StreamWriter. I created a sample application that sends a base64 encoded image in a stream and then I decoded it and loaded it with RasterCodecs and it works.
Try modifying your code to the following:
Code:public Stream LoadFromData(Stream streamData, int pageNumber, int resolution, string mimeType, int bitsPerPixel, int qualityFactor, int width, int height)
{
// document data is not optional
StreamReader reader = new StreamReader(streamData);
string docData = reader.ReadToEnd();
reader.Close();
reader.Dispose();
if (string.IsNullOrEmpty(docData))
throw new ArgumentNullException("Document Data");
if (pageNumber < 0)
throw new ArgumentException("'pageNumber' must be a value greater than or equals to 0");
// Default is page 1
if (pageNumber == 0)
pageNumber = 1;
if (resolution < 0)
throw new ArgumentException("'resolution' must be a value greater than or equals to 0");
// Sanity check on other parameters
if (qualityFactor < 0 || qualityFactor > 100)
throw new ArgumentException("'qualityFactor' must be a value between 0 and 100");
if (width < 0 || height < 0)
throw new ArgumentException("'width' and 'height' must be value greater than or equal to 0");
// Get the image format
SaveImageFormat saveFormat = SaveImageFormat.GetFromMimeType(mimeType);
try
{
MemoryStream ms = new MemoryStream(Convert.FromBase64String(docData));
using (RasterCodecs codecs = new RasterCodecs())
{
ServiceHelper.InitCodecs(codecs, resolution);
// Load the page
using (RasterImage image = codecs.Load(ms, 0, CodecsLoadByteOrder.BgrOrGray, pageNumber, pageNumber))
{
// Resize it (will only resize if both width and height are not 0), will also take care of FAX images (with different resolution)
ImageResizer.ResizeImage(image, width, height);
// We need to find out the format, bits/pixel and quality factor
// If the user gave as a format, use it
if (saveFormat == null)
{
// If the user did not give us a format, use PNG
saveFormat = new PngImageFormat();
mimeType = "image/png";
}
saveFormat.PrepareToSave(codecs, image, bitsPerPixel, qualityFactor);
// Save it to a memory stream
MemoryStream ms = new MemoryStream();
codecs.Save(image, ms, saveFormat.ImageFormat, saveFormat.BitsPerPixel);
ms.Position = 0;
// Set the MIME type and Content-Type if there is a valid web context
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
currentContext.OutgoingResponse.ContentType = mimeType;
currentContext.OutgoingResponse.ContentLength = ms.Length;
}
return ms;
}
}
}
catch (Exception ex)
{
Log(string.Format("LoadFromData - Error:{1}{0} PageNumber:{2}", Environment.NewLine, ex.Message, pageNumber));
throw ex;
}
}
Hadi Chami
Developer Support Manager
LEAD Technologies, Inc.
#3
Posted
:
Tuesday, May 16, 2017 7:55:32 AM(UTC)
Groups: Registered
Posts: 20
Ah. Thank you for your help. That worked. Looks like I was overthinking the MemoryStream that read the docData.
LEADTOOLS Support
General
General Questions
How to use Raster Service without creating a temporary file?
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.