I'm having a heck of a time with creating thumbnails and then converting them into a byte array. I've tried three methods, and all 3 times I get an error.
The first was using Bitmap.GetThumbnailImage, which I have used in the past and then saved directly into Response.OutputStream
The second was using System.Drawing.Graphics with DrawImage(). Still no go.
The third was just to create a new bitmap, pass in the old bitmap, and set the new size. Same error.
Value cannot be null.
Parameter name: encoder
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: encoder
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ArgumentNullException: Value cannot be null.
Parameter name: encoder]
System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) +615244
Here is the code for my method. Maybe someone will see what I'm doing wrong. In case you aren't sure about GetThumbSize, it's simply a method that takes in the image size and the maximum thumb size and then computes an actual size to preserve the aspect ratio.
public static System.Drawing.Image.GetThumbnailImageAbort thumbnailCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
public static bool ThumbnailCallback()
{
return false;
}
/// <summary>
///
/// </summary>
/// <param name="image"></param>
/// <param name="size"></param>
/// <remarks>
/// This method will throw a AccessViolationException when the machine OS running the server code is windows 7.
/// </remarks>
/// <returns></returns>
public static byte[] CreateThumbnail(byte[] imageData, Size size)
{
using (MemoryStream inStream = new MemoryStream())
{
inStream.Write(imageData, 0, imageData.Length);
using (System.Drawing.Image image = Bitmap.FromStream(inStream))
{
Size thumbSize = GetThumbSize(new Size(image.Width, image.Height), size);
//do not make image bigger
if (thumbSize.Equals(image.Size) || (image.Width < size.Width || image.Height < size.Height))
{
//if no shrinking is ocurring, return the original bytes
return imageData;
}
else
{
using (System.Drawing.Image thumb = image.GetThumbnailImage(thumbSize.Width, thumbSize.Height, thumbnailCallback, IntPtr.Zero))
{
using (MemoryStream outStream = new MemoryStream())
{
thumb.Save(outStream, thumb.RawFormat);
return outStream.ToArray();
}
}
}
}
}
}
This line is throwing the error:
thumb.Save(outStream, thumb.RawFormat);
Any ideas? Thanks for the help!
I think the problem may be the original image's encoding. IIRC, Save(stream, format) results in a call to Save(stream, encoder, params), with the encoder being taken from the format; which in your case is the original format of the image.
According to the Community Content for the Save method, some formats will not translate well into an appropriate encoder.
I would suggest you specify the encoder yourself, using some standard format like PNG.
Try:
thumb.Save(outStream, ImageFormat.Png, null); // optionally add encoder parameters here, like quality or luminescence
If what you are trying to do is save it in a Raw format you can try the following, as in my case it works when the original image format is a supported one:
try
{
thumb.Save(outStream, img.RawFormat);
}
catch (System.ArgumentNullException)
{
thumb.Save(outStream, ImageFormat.Png);
}
Related
While attempting to troubleshoot a use case I get a "Bad signature (0x01549FF9) at position 0x001D4DA8" exception after trying to open the workbook. What is the best way to find what part of the xlsx xml is causing this issue?
Opening the file in Excel and saving it resolves the issue and I can see from diffs that Excel must have found and corrected "errors" but there are too many to definitively figure out which one is the issue.
[TestMethod]
public void FileSaving_FileOpensAfterMultipleEdits_FunctioningFile()
{
var template = #"C:\xxxxx\test.xlsx";
var outputSmokeTest = Path.Combine(testDocumentsRootDirectory, #"Results\CorruptTest.xlsx");
smokeTestWorkbook = new Workbook(key);
if (File.Exists(outputSmokeTest))
File.Delete(outputSmokeTest);
smokeTestWorkbook.Open(template);
smokeTestWorkbook.SaveAs(outputSmokeTest);
}
/// <summary>
/// Opens a reference to the workbook
/// </summary>
/// <returns></returns>
public void Open(string workbookPath)
{
var loggerString = "Open";
if (File.Exists(workbookPath))
{
try
{
logger.Track(loggerString);
excelPackage = new ExcelPackage(new FileInfo(workbookPath));
}
catch (Exception ex)
{
logger.TrackException(loggerString, ex);
}
}
}
the new ExcelPackage line is what causes the exception.
I am new to react-native and I seek your help please. What I am planning to do is to get the app icon associated with an app that the user has installed on his device.
I did take a look at this code and realized that I have no way of passing it back to my JS.
Here is what I am doing currently.
private List<String> getNonSystemApps() {
List<PackageInfo> packages = this.reactContext
.getPackageManager()
.getInstalledPackages(0);
List<String> ret = new ArrayList<>();
for (final PackageInfo p: packages) {
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", p.packageName);
jsonObject.put("firstInstallTime", p.firstInstallTime);
jsonObject.put("installLocation", p.installLocation);
jsonObject.put("applicationInfo", p.applicationInfo);
jsonObject.put("permissions", getPermissionsByPackageName(p.packageName));
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
ret.add(jsonObject.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ret;
}
Can you please help me out with this ?
Thanks
Edit
I managed to get it working, based on Aaron's suggestion, I created another private function just to work with the images. This function will generate the base 64 version of an app's icon.
private String getBitmapOfAnAppAsBase64(String packageName) {
if(packageName.isEmpty() ) return new String("");
String base64Encoded = "";
Bitmap bitmap;
try {
Drawable appIcon = this.reactContext.getPackageManager().getApplicationIcon(packageName);
if(appIcon instanceof BitmapDrawable) {
bitmap= ((BitmapDrawable)appIcon).getBitmap();
} else {
bitmap = Bitmap.createBitmap(appIcon.getIntrinsicWidth(), appIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
base64Encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
} catch(Exception e) {
Log.d(TAG,"An error was encounted while getting the package information. The error follows : " + e.toString());
}
return base64Encoded;
}
I then use this generated string in my original function, with the following modifications.
Old Non working code
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
New working code
jsonObject.put("icon", getBitmapOfAnAppAsBase64(p.packageName));
and then in React-Native - its a piece of pie, since it supports base64 already.
"icon" : 'data:image/png;base64,'+installAppObj.icon
Huge thanks to Aaron , for guiding me in the correct direction.
If you haven't already, read through the entire Android Native Modules page. It's not that long and addresses several issues you're likely to run into.
Only these types can be sent to your JS code (via a #ReactMethod):
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
So you effectively have two options:
Encode the Drawable to one of these types, then decode it on the JavaScript side, or
Write the file to disk, and send the path over
I'm not sure what type of Drawable the icon is or if there are guarantees. But any of them should be convertible in some way. For example if it's a Bitmap you can do a Bitmap to Base64 String conversion.
How do can I read through a baml stream that contains a ResourceDictionaory using the Baml2006Reader and without acually instantiating the the ResourceDictionary?
I can ready through regular baml that just contains a UserControl just fine and I can examine the XAML tree using Baml2006Reader.NodeType etc.
But once the reader hits a ResourceDictionary, Baml2006Reader.Member.Name is "DeferrableContent" and Baml2006Reader.Value contains a MemoryStream that can not be parsed by another instance of Baml2006Reader. I can't event instantiate the reader:
System.IO.EndOfStreamException occurred HResult=-2147024858
Message=Unable to read beyond the end of the stream. Source=mscorlib
StackTrace:
at System.IO.MemoryStream.InternalReadInt32()
at System.Windows.Baml2006.Baml2006Reader.Process_Header()
at WpfApplication10.AssemblyExtensions.Read(Stream stream, List`1 result) in d:\Documents\Visual Studio
2012\Projects\WpfApplication10\WpfApplication10\AssemblyExtensions.cs:line
84 InnerException:
It seems that whenever the Baml2006Reader encounters an element where Baml2006Reader.Member.Name is "DeferrableContent" it is followed by another node where BamlReader.Value is a MemoryStream. It seems that this stream only contains a baml fragment and does not have a header (that's why System.Windows.Baml2006.Baml2006Reader.Process_Header() fails.)
So we need to tell the baml reader to read a baml fragment. This can be done be giving the reader an instance of System.Windows.Baml2006.Baml2006ReaderSettings where the IsBamlFragment property istrue.
Unfortunately both the Baml2006ReaderSettings class and the appropriate constructor of Baml2006Reader are internal. So we need to resort to reflection:
private static string PresentationFrameworkAssemblyName = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
private static Baml2006Reader CreateBamlFragmentReader(MemoryStream substream, XamlSchemaContext schemaContext)
{
var bamlSettingsType =
Type.GetType(
"System.Windows.Baml2006.Baml2006ReaderSettings, " + PresentationFrameworkAssemblyName);
var settingsCtor =
bamlSettingsType.GetConstructor(Type.EmptyTypes);
var bamlSettings = settingsCtor.Invoke(null);
var isBamlFragmentProp = bamlSettingsType.GetProperty("IsBamlFragment",
BindingFlags.NonPublic |
BindingFlags.Instance);
isBamlFragmentProp.SetValue(bamlSettings, true, null);
var ctor = typeof (Baml2006Reader).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new[]
{
typeof (Stream),
Type.GetType(
"System.Windows.Baml2006.Baml2006SchemaContext, " + PresentationFrameworkAssemblyName),
bamlSettingsType
},
null);
return (Baml2006Reader)ctor.Invoke(new[] { substream, schemaContext, bamlSettings });
}
usage:
var substream = reader.Value as MemoryStream;
if (substream != null)
{
using (var subReader = CreateBamlFragmentReader(substream, reader.SchemaContext))
{
// continue reading with subReader
}
}
I know this is rather fragile code and very hackish, but what the heck - it works (for me, currently)!
BACKGROUND
I have a media file that I am progressively downloading to my Silverlight 4 application, using WebClient.OpenReadAsync/OpenReadCompleted, and Stream.BeginRead/AsyncCallback. The goal is to play the file in a MediaElement by calling the SetSource method, passing in an instance of our custom MediaStreamSource, so that the file can start playing before the entire contents of the file have been downloaded. The media file is using custom encoding/decoding, which is why we are using a custom MediaStreamSource. Our MediaStreamSource is built to accept a Stream and begin parsing track information and play back in a MediaElement. I have confirmed I am progressively downloading the file contents. Here is a summary of the download code:
public void SetSource(string sourceUrl)
{
var uriBuilder = new UriBuilder(sourceUrl);
WebClient webClient = new WebClient();
// AllowReadStreamBuffering = false allows us to get the stream
// before it's finished writing to it.
webClient.AllowReadStreamBuffering = false;
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uriBuilder.Uri);
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
_inboundVideoStream = e.Result;
BeginReadingFromStream();
}
private void BeginReadingFromStream()
{
if (_inboundVideoStream.CanRead)
{
_chunk = new byte[_chunkSize];
_inboundVideoStream.BeginRead(_chunk, 0, _chunk.Length, new AsyncCallback(BeginReadCallback), _inboundVideoStream);
}
}
private void BeginReadCallback(IAsyncResult asyncResult)
{
Stream stream = asyncResult.AsyncState as Stream;
int bytesRead = stream.EndRead(asyncResult);
_totalBytesRead += bytesRead;
if (_playableStream == null)
_playableStream = new MemoryStream();
_playableStream.Write(_chunk, 0, _chunk.Length);
if (!_initializedMediaStream && _playableStream.Length >= _minimumToStartPlayback)
{
_initializedMediaStream = true;
// Problem: we can't hand the stream source a stream that's still being written to
// It's Position is at the end. Can I read and write from the same stream or is there another way
MP4MediaStreamSource streamSource = new MP4MediaStreamSource(_playableStream);
this.Dispatcher.BeginInvoke(() =>
{
mediaElement1.SetSource(streamSource);
});
}
if (_totalBytesRead < _fileSize)
{
ReadFromDownloadStream();
}
else
{
// Finished downloading
}
}
I've tried both writing/reading to a MemoryStream simultaneously, as listed above, as well as writing to an IsolatedStorageFile and reading from that file as I'm writing to it. So far I can't find a way to make either approach work.
QUESTION:
Is there a way to read and write to the same stream? Or is there a standard way to implement this with a stream and MediaStreamSource?
Thanks
The way I did it in my MediaStreamSource implementation is to have 2 streams in it: one for reading and one for writing.
I dispose and re-create the reading stream using the buffer of the writing stream every time GetSampleAsync() is called. Another way to do it I guess is to use a negative offset when creating a MediaStreamSample to pass to ReportGetSampleCompleted() since the position of the stream will always be at the end, but you have to make sure that the position is at the end otherwise this will not work, to keep it simple I just used 2 streams
I am currently using sockets to try and send messages between a Silverlight 3 client and a .NET3.5 service. I can set up the TCP connection fine, and send data across, but my issue comes with serialising and deserialising DataContracts.
Currently we are using WCF PollingDuplex binding to do this work, but we are not happy with its performance, so are trying sockets, whilst still attempting to make use of DataContract attributes. The code I have is as follows:
// Client
public void Send(ActionMessage actionMessage)
{
DataContractSerializer dcs =
new DataContractSerializer(actionMessage.GetType());
MemoryStream memoryStream = new MemoryStream();
dcs.WriteObject(memoryStream, actionMessage);
byte[] sendBuffer = new byte[4096];
memoryStream.Position = 0;
memoryStream.Read(sendBuffer, 0, sendBuffer.Length);
SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
socketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
if(!_socket.SendAsync(socketAsyncEventArgs))
HandleSendComplete(socketAsyncEventArgs);
}
// Service
private byte[] _recieveBuffer = new byte[4096];
private int _receivedLength;
private void socket_OnReceiveComplete(IAsyncResult asyncResult)
{
_receivedLength += _tcpClient.Client.EndReceive(asyncResult);
// See if there's more data that we need to grab
if (_receivedLength < _recieveBuffer.Length)
{
// Need to grab more data so receive remaining data
_tcpClient.Client.BeginReceive(_recieveBuffer, _receivedLength,
_recieveBuffer.Length - _receivedLength, SocketFlags.None,
new AsyncCallback(socket_OnReceiveComplete), null);
return;
}
MemoryStream memoryStream = new MemoryStream();
memoryStream.Position = 0;
memoryStream.Write(_recieveBuffer, 0, _recieveBuffer.Length);
DataContractSerializer dcs = new DataContractSerializer(typeof(ActionMessage));
object o = dcs.ReadObject(memoryStream);
ActionMessage actionMessage = (ActionMessage) o;
}
It is the ReadObject line that throws the XmlException: Unexpected End of File. I have tried various things including truncating trailing 0's from the byte array (_recieveBuffer) when it is received, leaving just one 0 at the end etc, but nothing seems to work. I have checked the byte[] buffers on the client and the server side and they have the same values at the beginning and end and are of the same length. I have also tried using actionMessage.GetType() and typeof(ActionMessage) as parameters to the DataContractSerializer, but there is no difference...
What am I misssing here: why does dataContractSerializer.Write() not accept the output generated by dataContractSerializer.Read() ?
I was having a good day until hitting this...I did find one other guy with the same problem, but the solution offered, to set memoryStream.Position = 0 on the service side did not work...
Thanks in advance.
If I had to guess, I would say that your memoryStream.Position = 0; line is in the wrong place.
You will need to reset position in the stream after writing the buffer into the stream.