I have a page that sends html5 canvas data, encoded as a base64 bmp image (using this algorithm http://devpro.it/code/216.html) to a serverside process that converts it into a System.Drawing.Image object and does some operations on it.
In my local environment, this works just fine, but on my ec2 instance I get the following error:
System.ArgumentException: Parameter is not valid. at
System.Drawing.Image.FromStream(Stream stream, Boolean
useEmbeddedColorManagement, Boolean validateImageData) at
System.Drawing.Image.FromStream(Stream stream, Boolean
useEmbeddedColorManagement)
My code looks as follows:
System.Drawing.Image image = null;
string b64string = "...";
byte[] sf = Convert.FromBase64String(b64string );
using (MemoryStream s = new MemoryStream(sf, 0, sf.Length))
{
image = System.Drawing.Image.FromStream(s, false);
}
...
Here’s a text file with a sample b64string that I’m using to test: https://docs.google.com/leaf?id=0BzVLGmig1YZ3MTM0ODBiNjItNzk4Yi00MzI5LWI5ZWMtMzU1OThlNWEyMTU5&hl=en_US
I’ve also tried the following and had the same results:
System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
image = converter.ConvertFrom(sf) as System.Drawing.Image;
Any insight would be greatly appreciated!
asked Sep 23, 2011 at 19:27
17
I still don’t know the real cause of your problem, but i guess it is related with a image format which Image
class doesn’t recognize. After inspecting the binary data a little bit, I could be able to form your image. I hope this helps.
Bitmap GetBitmap(byte[] buf)
{
Int16 width = BitConverter.ToInt16(buf, 18);
Int16 height = BitConverter.ToInt16(buf, 22);
Bitmap bitmap = new Bitmap(width, height);
int imageSize = width * height * 4;
int headerSize = BitConverter.ToInt16(buf, 10);
System.Diagnostics.Debug.Assert(imageSize == buf.Length - headerSize);
int offset = headerSize;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
bitmap.SetPixel(x, height - y - 1, Color.FromArgb(buf[offset + 3], buf[offset], buf[offset + 1], buf[offset + 2]));
offset += 4;
}
}
return bitmap;
}
private void Form1_Load(object sender, EventArgs e)
{
using (FileStream f = File.OpenRead("base64.txt"))
{
byte[] buf = Convert.FromBase64String(new StreamReader(f).ReadToEnd());
Bitmap bmp = GetBitmap(buf);
this.ClientSize = new Size(bmp.Width, bmp.Height);
this.BackgroundImage = bmp;
}
}
answered Oct 19, 2011 at 13:04
L.BL.B
114k19 gold badges177 silver badges224 bronze badges
4
The posted code seems correct. I have tested it and it works fine.
The exception «System.ArgumentException: Parameter is not valid.» without any other hint (especially not the name of the parameter) is a wrapper for GDI+ (the underlying technology behind .NET Image class) standard InvalidParameter error, which does not tell use exactly what parameter is invalid.
So, following the FromStream
code with .NET Reflector, we can see that the parameters used in GDI+ calls are essentially … the input stream.
So my guess is the input stream you provide is sometimes invalid as an image? You should save the failing input streams (using File.SaveAllBytes(sf) for example) for further investigation.
answered Oct 19, 2011 at 18:20
Simon MourierSimon Mourier
131k21 gold badges245 silver badges295 bronze badges
6
This could happen if sf
contained invalid image data. Verify the validity of the data you’re passing into the stream, and see if that fixes your issue.
answered Oct 25, 2011 at 18:54
James JohnsonJames Johnson
45.4k8 gold badges72 silver badges110 bronze badges
- Remove From My Forums
-
Question
-
Hi, i have this application that will display an image in a picture box and I am getting an error «Parameter is not valid».
The image to be displayed is from SQL SERVER 2008 database and the image datatype is varbinary(max). There are only few images that throw «Parameter is not valid» error.
Here is the code snippet:
byte[] getImage = (byte[])dr[«image»];
MemoryStream ms = new MemoryStream(getImage);object objImg = new Bitmap(Bitmap.FromStream(ms)); // error occurs here
pictureBox1.Image = new Bitmap(Bitmap.FromStream(ms));I checked different forums but no one can tell how to fix this error. Hope you can help me.
Thanks in advance
Cyrilla
Answers
-
DataSet tds = new DataSet();
SqlConnection cn = new SqlConnection(«connection string»);
SqlCommand cmd = new SqlCommand(«select * from [table name]», cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(tds, «image»);
byte[] getImage = new byte[0];
foreach (DataRow dr in tds.Tables [0].Rows)
{
getImage = (byte[])dr[«imagePath»]; //column name //from your codes
}
MemoryStream ms = new MemoryStream(getImage); //from your codes
object objImg = new Bitmap(Bitmap.FromStream(ms)); //from your codes
pictureBox1.Image = new Bitmap(Bitmap.FromStream(ms)); //from your codes
If a post answers your question, please click «Mark As Answer»
on that post and «Mark as Helpful-
Marked as answer by
Monday, July 4, 2011 3:40 AM
-
Marked as answer by
-
check that if all the images you are having in db are of .bmp type. There may be a case where the byte format of the image stored not as per Bitmap .bmp file standards causing an error. I think it wld be better to first load image, then save it in your case
want to show up in picture box.MemoryStream ms = new MemoryStream(getImage);
Bitmap bmp = (Bitmap)Image.FromStream(ms); bmp.Save(@"C:file.jpg"); bmp.Dispose();
Mark Answered, if it solves your query
Rohit Arora-
Marked as answer by
Leo Liu — MSFTModerator
Monday, July 4, 2011 3:40 AM
-
Marked as answer by
This issue has been moved from a ticket on Developer Community.
Hello,
I am trying to develop a Paint-like program with the ability to store the graphical commands in simple text format in order to make them reusable and easily modifiable. When added an «undo» function to the program found this problem with Drawstring. Created a simple demo program to show it. It contains a 512*512 pixel Picturebox and 4 buttons:
ButtonReadfont: start a font dialog, display the font name in the lower right area of the Picturebox with Drawstring..
ButtonDrawrect: draw a filled rectangle in the upper left area of the Picturebox (and save the previous bitmap state before drawing).
ButtonUndo: restore the previous bitmap state.
ButtonClear: clear the Picturebox (fill it with black color).
If the ButtonReadfont is used first then it works as expected.
If the ButtonDrawrect is used first (even without using the ButtonUndo) then it modifies something which makes Drawstring unusable (every further use of ButtonReadfont produces no drawing just the error message «System.ArgumentException: Parameter is not valid.»). Other graphical functions (like Fillrectangle in this demo) are not affected.
Please inspect it (is it an error in Visual Basic or I should do something differently).
Best regards: Csaba
Public Class Form1
' simple program to demonstrate the DrawString problem
' (error "System.ArgumentException: Parameter is not valid.")
' compiler/builder: Microsoft Visual Studio Community 2019, Version 16.11.5 with .NET Framework Version 4.8.04084
' global variables
Public point1x As Integer = 10
Public point1y As Integer = 10
Public defPen = New Pen(Color.Green, 1)
Public defBrush = New SolidBrush(Color.Red)
Public defFont As Font
Public bgbm As New Bitmap(512, 512) ' background drawing area
Public bgbm2 As New Bitmap(512, 512) ' used for "undo latest draw"
Public grbgbm As Graphics = Graphics.FromImage(bgbm)
Public grbgbm2 As Graphics = Graphics.FromImage(bgbm2)
Public Function Showpicture() As Integer
' display the content of the background drawing area in the Picturebox1
Dim rect512 As Rectangle = New Rectangle(0, 0, 512, 512) ' Picturebox1
Dim grpicture As Graphics = PictureBox1.CreateGraphics
' set low quality rendering in order to enforce pixel to pixel copy
grpicture.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed
grpicture. InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
grpicture. PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None
grpicture. SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
grpicture.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy
grpicture. DrawImage(bgbm, rect512, 0, 0, 512, 512, GraphicsUnit.Pixel)
Return 0
End Function ' Showpicture
Private Sub ButtonReadfont_Click(sender As Object, e As EventArgs) Handles ButtonReadfont.Click
' start an interactive font dialog, display the result in the lower-right area of Picturebox1
Dim str1 As String = ""
Dim fdlg As New FontDialog
If fdlg. ShowDialog() = Windows.Forms.DialogResult.OK Then
str1 = fdlg. Font.Name
defFont = fdlg. Font
grbgbm. FillRectangle(defBrush, 400, 400, 100, 20) ' debug - show that defBrush is ok
grbgbm. DrawRectangle(defPen, 400, 450, 100, 20) ' debug - expected area of font name drawing
Showpicture()
MessageBox.Show("Readfont debug: " & str1)
grbgbm. DrawString(str1, defFont, defBrush, 400, 450)
Showpicture()
End If
End Sub
Private Sub ButtonDrawrect_Click(sender As Object, e As EventArgs) Handles ButtonDrawrect.Click
' display a rectangle in the upper left area of the Picturebox1
Dim rect512 As Rectangle = New Rectangle(0, 0, 512, 512) ' for bitmap copy
' set grbgbm to low quality rendering
grbgbm.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed
grbgbm. InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
grbgbm. PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None
grbgbm. SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
grbgbm.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy
' the same settings for grbgbm2
grbgbm2.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed
grbgbm2. InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
grbgbm2. PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None
grbgbm2. SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None
grbgbm2.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy
' for undo:
grbgbm2. DrawImage(bgbm, rect512, 0, 0, 512, 512, GraphicsUnit.Pixel)
' drawing the rectangle, increasing point1 coordinates in order to make multiple drawings different
grbgbm. FillRectangle(defBrush, point1x, point1y, 30, 10)
Showpicture()
point1x += 10
point1y += 10
End Sub
Private Sub ButtonUndo_Click(sender As Object, e As EventArgs) Handles ButtonUndo.Click
' undo the last draw command
' it is assumed here that before every draw operation the previous picture is saved in bgbm2
Dim rect512 As Rectangle = New Rectangle(0, 0, 512, 512)
grbgbm. DrawImage(bgbm2, rect512, 0, 0, 512, 512, GraphicsUnit.Pixel)
Showpicture()
End Sub
Private Sub ButtonClear_Click(sender As Object, e As EventArgs) Handles ButtonClear.Click
' fill the picturebox1 with one color
grbgbm. Clear(Color.Black)
Showpicture()
point1x = 10
point1y = 10
End Sub
End Class
Original Comments
Feedback Bot on 11/12/2021, 01:49 PM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Jenna Zheng [MSFT] on 11/15/2021, 03:48 PM:
Hi Csaba,
Thanks for your feedback, I’m sorry that I cannot reproduce this issue, does this reproduce for all project or specific project? If it’s reproduce with the specific project, which project do you use? For us to investigate this further, we must reproduce this issue on our side first, so could you please provide the details reproduced steps or sample project for us? We look forward to hearing from you!
Thanks,
Jenna
Csaba Kecskes on 11/17/2021, 01:38 AM:
Hello Jenna,
It’s not very clear for me what do you mean by “project”.
The demo program which I sent to you (see above) reproduces
the problem with 100% reliability on my PC.
(the original application in which I found it first
also reproduces it consistently)
At the beginning of the demo program the SW environment versions
(on my PC) are written in a comment line:
Microsoft Visual Studio Community 2019, Version 16.11.5
.NET Framework Version 4.8.04084
The Windows version on my PC:
Windows 10 Home, version 21H1, build number 19043.1348
(the language setting of this Windows is Hungarian, not English)
On my PC the demo program can be found in the following directory:
C:UsersCsabasourcereposDrawstringProblem
This directory contains the following files:
ApplicationEvents.vb
DrawstringProblem.sln
DrawstringProblem.vbproj
DrawstringProblem.vbproj.user
Form1.Designer.vb
Form1.resx
Form1.vb
The content of the Form1.vb file is the source code of the program which
was sent to you in the previous message.
The texts from the other files are copied below, I hope that these texts
contain all the necessary informations.
Best regards: Csaba
'--------------------------------------------------------------------ApplicationEvents.vb:
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
' The following events are available for MyApplication:
' Startup: Raised when the application starts, before the startup form is created.
' Shutdown: Raised after all application forms are closed. This event is not raised if the application terminates abnormally.
' UnhandledException: Raised if the application encounters an unhandled exception.
' StartupNextInstance: Raised when launching a single-instance application and the application is already active.
' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
' **NEW** ApplyHighDpiMode: Raised when the application queries the HighDpiMode to set it for the application.
' Example:
' Private Sub MyApplication_ApplyHighDpiMode(sender As Object, e As ApplyHighDpiModeEventArgs) Handles Me.ApplyHighDpiMode
' e.HighDpiMode = HighDpiMode.PerMonitorV2
' End Sub
Partial Friend Class MyApplication
End Class
End Namespace
'------------------------------------------------------------DrawstringProblem.sln:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31729.503
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "DrawstringProblem", "DrawstringProblem.vbproj", "{AD0F1E16-FA7A-4554-812A-8E0C7B673ED3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AD0F1E16-FA7A-4554-812A-8E0C7B673ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD0F1E16-FA7A-4554-812A-8E0C7B673ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD0F1E16-FA7A-4554-812A-8E0C7B673ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD0F1E16-FA7A-4554-812A-8E0C7B673ED3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {83E7DE4A-FCE1-4A8D-A55C-41269654CBFC}
EndGlobalSection
EndGlobal
'------------------------------------------------------------------DrawstringProblem.vbproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>DrawstringProblem</RootNamespace>
<StartupObject>Sub Main</StartupObject>
<UseWindowsForms>true</UseWindowsForms>
<MyType>WindowsForms</MyType>
</PropertyGroup>
<ItemGroup>
<Import Include="System.Data" />
<Import Include="System.Drawing" />
<Import Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Update="My ProjectApplication.Designer.vb">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="My ProjectApplication.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
</Project>
'-----------------------------------------------------------------DrawstringProblem.vbproj.user:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Update="Form1.vb">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>
'-----------------------------------------------------------------Form1.Designer.vb:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label()
Me.PictureBox1 = New System.Windows.Forms.PictureBox()
Me.ButtonReadfont = New System.Windows.Forms.Button()
Me.ButtonDrawrect = New System.Windows.Forms.Button()
Me.ButtonUndo = New System.Windows.Forms.Button()
Me.ButtonClear = New System.Windows.Forms.Button()
CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(8, 8)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(144, 20)
Me.Label1.TabIndex = 0
Me.Label1.Text = "DrawString problem"
'
'PictureBox1
'
Me.PictureBox1.Location = New System.Drawing.Point(8, 84)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(512, 512)
Me.PictureBox1.TabIndex = 1
Me.PictureBox1.TabStop = False
'
'ButtonReadfont
'
Me.ButtonReadfont.Location = New System.Drawing.Point(8, 36)
Me.ButtonReadfont.Name = "ButtonReadfont"
Me.ButtonReadfont.Size = New System.Drawing.Size(132, 28)
Me.ButtonReadfont.TabIndex = 2
Me.ButtonReadfont.Text = "Select font"
Me.ButtonReadfont.UseVisualStyleBackColor = True
'
'ButtonDrawrect
'
Me.ButtonDrawrect.Location = New System.Drawing.Point(164, 36)
Me.ButtonDrawrect.Name = "ButtonDrawrect"
Me.ButtonDrawrect.Size = New System.Drawing.Size(136, 28)
Me.ButtonDrawrect.TabIndex = 3
Me.ButtonDrawrect.Text = "Draw rectangle"
Me.ButtonDrawrect.UseVisualStyleBackColor = True
'
'ButtonUndo
'
Me.ButtonUndo.Location = New System.Drawing.Point(320, 36)
Me.ButtonUndo.Name = "ButtonUndo"
Me.ButtonUndo.Size = New System.Drawing.Size(140, 28)
Me.ButtonUndo.TabIndex = 4
Me.ButtonUndo.Text = "Undo"
Me.ButtonUndo.UseVisualStyleBackColor = True
'
'ButtonClear
'
Me.ButtonClear.Location = New System.Drawing.Point(476, 36)
Me.ButtonClear.Name = "ButtonClear"
Me.ButtonClear.Size = New System.Drawing.Size(144, 28)
Me.ButtonClear.TabIndex = 5
Me.ButtonClear.Text = "Clear picturebox"
Me.ButtonClear.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 20.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(752, 601)
Me.Controls.Add(Me.ButtonClear)
Me.Controls.Add(Me.ButtonUndo)
Me.Controls.Add(Me.ButtonDrawrect)
Me.Controls.Add(Me.ButtonReadfont)
Me.Controls.Add(Me.PictureBox1)
Me.Controls.Add(Me.Label1)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents Label1 As Label
Friend WithEvents PictureBox1 As PictureBox
Friend WithEvents ButtonReadfont As Button
Friend WithEvents ButtonDrawrect As Button
Friend WithEvents ButtonUndo As Button
Friend WithEvents ButtonClear As Button
End Class
'--------------------------------------------------------------Form1.resx:
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="https://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
'-----------------------------------------------------------------------------
Jenna Zheng [MSFT] on 11/17/2021, 02:03 PM:
Hi Csaba,
I’m sorry that I cannot repro your problem, For us to investigate this further, please you provide a simple demo app to me, If you paste a large piece of code like that, I copy it. There are too many problems in the project and I can’t debug it at all. Only if you provide your project to me, can I debug and investigate your problem. I suspect this is not the problem of vs itself, but the problem of your code.
Thanks,
Jenna
Csaba Kecskes on 11/18/2021, 07:18 PM:
Hello Jenna,
I tried to create an even simpler demo program for this Drawstring problem.
I went through the following steps:
- start Visual Studio 2019
- choose “Create new project” -> “Windows Forms app and Visual Basic”
- set “Project name: DrawstringProblem2”, “Location: C:UsersCsabasourcerepos”,
“Place solution and project in the same directory” - set “Target Framework: .NET 5.0”
- click “Create”, the “Form1.vb [Design]” window appears
- using the Toolbox, create four graphical objects within the Form1:
- a button named ButtonReadfont
- a button named ButtonDrawrect
- a button named ButtonUndo
- a picturebox named Picturebox1 with size 512 * 512 pixels
- add the source code to “Form1.vb” which I added below in this message
- from the Visual Studio menu, select “Debug” -> “Start debugging”
- click on the ButtonReadfont, a font dialog will be started and the
name of the selected font will be displayed in the lower right area of Picturebox1 - click on the ButtonDrawrect, a filled rectangle will appear in the
upper left area of Picturebox1 - click on the ButtonReadfont again, a font dialog will be started again but
the name of the selected font will not be displayed because now the DrawString will fail
(error “System.ArgumentException: Parameter is not valid.” appears in Visual Studio
at the program line which contains the Drawstring call)
I suppose you are using a PC (or a virtual machine) with Windows Enterprise and
English language settings. If the problem cannot be reproduced on your PC then
you should try it on an other PC (or virtual machine) with Windows 10 Home
and some not-English (not necessarily Hungarian) language settings.
Best regards: Csaba
' even simpler program to demonstrate the DrawString problem ' (error "System.ArgumentException: Parameter is not valid.") ' global variables Public rect512 As Rectangle = New Rectangle(0, 0, 512, 512) ' size of Picturebox1 Public point1x As Integer = 10 Public point1y As Integer = 10 Public defPen = New Pen(Color.Green, 1) Public defBrush = New SolidBrush(Color.Red) Public defFont As Font Public bgbm As New Bitmap(512, 512) ' background drawing area Public bgbm2 As New Bitmap(512, 512) ' used for "undo latest draw" Public grbgbm As Graphics = Graphics.FromImage(bgbm) Public grbgbm2 As Graphics = Graphics.FromImage(bgbm2) ' global functions Public Function Showpicture() As Integer ' display the content of the background drawing area in the Picturebox1 Dim grpicture As Graphics = PictureBox1.CreateGraphics ' cannot be global? ' set low quality rendering in order to enforce pixel to pixel copy grpicture.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None grpicture.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy ' copy from bgbm to Picturebox1 grpicture.DrawImage(bgbm, rect512, 0, 0, 512, 512, GraphicsUnit.Pixel) Return 0 End Function ' Showpicture
<span class="hljs-keyword">Private</span> Sub ButtonReadfont_Click(sender <span class="hljs-keyword">As</span> <span class="hljs-keyword">Object</span>, e <span class="hljs-keyword">As</span> EventArgs) Handles ButtonReadfont.Click <span class="hljs-string">' start an interactive font dialog, display the result in the lower-right area of Picturebox1 Dim str1 As String = "" Dim fdlg As New FontDialog If fdlg.ShowDialog() = Windows.Forms.DialogResult.OK Then defFont = fdlg.Font str1 = defFont.Name grbgbm.FillRectangle(defBrush, 400, 400, 100, 20) '</span> debug - <span class="hljs-keyword">show</span> that defBrush <span class="hljs-keyword">is</span> ok grbgbm.DrawRectangle(defPen, <span class="hljs-number">400</span>, <span class="hljs-number">450</span>, <span class="hljs-number">100</span>, <span class="hljs-number">20</span>) <span class="hljs-string">' debug - expected area of font name drawing Showpicture() MessageBox.Show("Readfont debug: " & str1) grbgbm.DrawString(str1, defFont, defBrush, 400, 450) Showpicture() End If End Sub Private Sub ButtonDrawrect_Click(sender As Object, e As EventArgs) Handles ButtonDrawrect.Click '</span> display a rectangle <span class="hljs-keyword">in</span> the <span class="hljs-keyword">upper</span> <span class="hljs-keyword">left</span> area <span class="hljs-keyword">of</span> the Picturebox1 <span class="hljs-string">' set grbgbm to low quality rendering grbgbm.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None grbgbm.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy '</span> the same <span class="hljs-keyword">settings</span> <span class="hljs-keyword">for</span> grbgbm2 grbgbm2.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None grbgbm2.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy <span class="hljs-string">' for undo (saving previous bitmap): grbgbm2.DrawImage(bgbm, rect512, 0, 0, 512, 512, GraphicsUnit.Pixel) '</span> drawing the rectangle, increasing point1 coord.s (make multiple drawings different) grbgbm.FillRectangle(defBrush, point1x, point1y, <span class="hljs-number">30</span>, <span class="hljs-number">10</span>) Showpicture() point1x += <span class="hljs-number">10</span> point1y += <span class="hljs-number">10</span> <span class="hljs-keyword">End</span> Sub <span class="hljs-keyword">Private</span> Sub ButtonUndo_Click(sender <span class="hljs-keyword">As</span> <span class="hljs-keyword">Object</span>, e <span class="hljs-keyword">As</span> EventArgs) Handles ButtonUndo.Click <span class="hljs-string">' undo the last draw command '</span> it <span class="hljs-keyword">is</span> assumed here that <span class="hljs-keyword">before</span> every draw operation the previous picture <span class="hljs-keyword">is</span> saved <span class="hljs-keyword">in</span> bgbm2 grbgbm.DrawImage(bgbm2, rect512, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">512</span>, <span class="hljs-number">512</span>, GraphicsUnit.Pixel) Showpicture() <span class="hljs-keyword">End</span> Sub
Original Solutions
(no solutions)
I’m getting a strange behaviour when uploading to the media library recently where
Images upload but the pop-up doesn’t close and an error is shown if I look in the network tab. The image actually does upload but with no height/width or alt text:
> [ArgumentException: Parameter is not valid.] > System.Drawing.Image.FromStream(Stream stream, Boolean > useEmbeddedColorManagement, Boolean validateImageData) +1545584 > Sitecore.Resources.Media.ImageMedia.GetImage() +64 > Sitecore.Resources.Media.ImageMedia.UpdateImageMetaData(MediaStream > mediaStream) +239 > Sitecore.Resources.Media.JpegMedia.UpdateMetaData(MediaStream > mediaStream) +63 > Sitecore.Resources.Media.MediaCreator.AttachStreamToMediaItem(Stream > stream, String itemPath, String fileName, MediaCreatorOptions options) > +282 Sitecore.Resources.Media.MediaCreator.CreateFromStream(Stream stream, String filePath, MediaCreatorOptions options) +117 > Sitecore.Resources.Media.MediaUploader.UploadToDatabase(List`1 list) > +487 Sitecore.Resources.Media.MediaUploader.Upload() +155 Sitecore.Pipelines.Upload.Save.Process(UploadArgs args) +1220 > > > [TargetInvocationException: Exception has been thrown by the target of > an invocation.] System.RuntimeMethodHandle.InvokeMethod(Object > target, Object[] arguments, Signature sig, Boolean constructor) +0 > System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, > Object[] parameters, Object[] arguments) +76 > System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags > invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) > +211 System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35 > Sitecore.Nexus.Pipelines.NexusPipelineApi.Resume(PipelineArgs args, > Pipeline pipeline) +398 > Sitecore.Pipelines.Pipeline.Start(PipelineArgs args, Boolean atomic) > +366 Sitecore.Shell.Applications.FlashUpload.Advanced.UploadTarget.HandleUpload() > +1525 Sitecore.Shell.Applications.FlashUpload.Advanced.UploadTarget.OnLoad(EventArgs > e) +852 System.Web.UI.Control.LoadRecursive() +71 > System.Web.UI.Page.ProcessRequestMain(Boolean > includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) > +3178
This is the call made to the uploadtarget.aspx
page which is returning a 500 error
:
> sitecore/shell/applications/flashupload/advanced/uploadtarget.aspx? > id=%7B487DBAD1-EFC7-4989-B0C1-1DAAAFD923F6%7D&la=en&language=en&vs=1 > &version=1&database=master&readonly=0&db=master&uploadID=851fea44-50b9-4dc3-8241-4dba5895ffe4
This has only just started happening and I’m not sure why as the permissions on the folder seem fine and we haven’t updated the code that I can think would affect this recently.
Further info: Sitecore 8.1 update 2.
Introduction
I find that it is quite common for people to have a problem loading an image from a database and recreating it as an Image for display — when they try to create the new Image,
it throws an exception reporting «Parameter is not valid.»
So, this explains why it happens, and (hopefully) will save me — and you — some typing in the future.
Background
Storing images in databases is such a handy idea, that everyone picks up on it at some stage. Indeed, it can be a good idea, provided the images are small,
or there aren’t too many of them, and provided that you only load them when you actually need them. Loading images from a DB when you don’t need them can waste
a lot of bandwidth, and slow your application down a serious amount.
But the problem is that it is also far too easy to get wrong — particularly if you use string
concatenation to assemble your SQL statements — and the error only shows up when you try to use the stored information.
It then looks like a fault in your reader code: «but it can’t be — it works! I got it form here!»
Loading images from the DB
The code to read an image from a DB and convert it to a Image for display is pretty easy:
using (SqlConnection con = DBAccess.DBCon) { using (SqlCommand cmd = new SqlCommand("SELECT picture FROM Pictures WHERE Id=@ID", con)) { cmd.Parameters.AddWithValue("@ID", Id); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { byte[] data = (byte[])reader["Picture"]; using (MemoryStream stream = new MemoryStream(bytes)) { myImage = new Bitmap(stream); } } } }
But — if the data is not a valid image for any reason, the line:
myImage = new Bitmap(stream);
will throw an exception: «Parameter is not valid.»
It is only if you actually look at the data returned from the database that you realise why — and it’s not so obvious when you glance at it in the debugger:
{byte[21]} [0] 83 [1] 121 [2] 115 [3] 116 [4] 101 [5] 109 [6] 46 [7] 68 [8] 114 [9] 97 [10] 119 [11] 105 [12] 110 [13] 103 [14] 46 ...
It doesn’t look like anything you recognise, so it could be your data — though the length of 21 bytes is a big clue: is your image likely to be only 21 bytes long?
That’s a pretty small image…
But it is readable, with a little practice. Each byte is an ASCII value, in decimal.
"83" is an uppercase 'S' "121" is an lowercase 'y' "115" is an lowercase 's' "116" is an lowercase 't' "101" is an lowercase 'e' "109" is an lowercase 'm' "46" is a '.' "68" is an uppercase 'D' "114" is an lowercase 'r' "97" is an lowercase 'a' "119" is an lowercase 'w' "105" is an lowercase 'i' "110" is an lowercase 'n' "103" is an lowercase 'g' "46" is an lowercase '.' ...
In short, the data you read from the database is a human readable string, that says
"System.Drawing.Bitmap"
When the Image class tries to convert it to an actual image, it can’t understand it at all, and throws the exception. The code works — it’s the data that is the problem.
Saving an image to the database
This is where you caused the problem!
Normally, this is as a result of concatenating strings to form an SQL command:
string sql = "INSERT INTO myTable (imageData) VALUES ('" + myImage + "')";
Does not include the image content in the SQL command — it calls the default Image.ToString
method, which returns the human readable Image type:
"System.Drawing.Bitmap"
So you end up with an SQL command:
INSERT INTO myTable (imageData) VALUES ('System.Drawing.Bitmap')
Which will not cause an error — but it will save the name of the image type as what you think is the Image data itself.
This is yet another reason why you should never concatenate string to form SQL commands. If you want the others, use Google: «Bobby Tables» should do it.
And please — don’t think they are joking!
Doing it properly isn’t difficult, or even that time consuming, and it can help to improve readability
as well as reliability. All you have to do is use a Parametrized Query.
First, convert the Image to an array of bytes:
Image myImage = Image.FromFile(@"D:TempMyPic.jpg"); byte[] data; using (MemoryStream ms = new MemoryStream()) { myImage.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); data = ms.ToArray(); }
Then, use the bytes in your SqlCommand
object:
using (SqlConnection con = new SqlConnection(strConnect)) { con.Open(); using (SqlCommand com = new SqlCommand("INSERT INTO Pictures (Picture) VALUES (@IM)", con)) { com.Parameters.AddWithValue("@IM", data); com.ExecuteNonQuery(); } }
Before I close…
No, you can’t retrieve the image data for the images you already stored wrongly — you will have to delete them all, and save them to the DB correctly!
Yes, yes — I know you knew that. But you would be surprised how many people it comes as a shock to!
History
Original version.
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word «the».
Invented the portable cat-flap.
Currently, has not died yet. Or has he?