. NET binary Image storage: When storing images in binary format, you must set the fields in the database to the Image data type (SQL Server). the stored data is Byte [].
1. the parameter is the image path: returned Byte [] type:
1. public byte [] GetPictureData (string imagepath)
2 .{
3. // open the file stream based on the path of the image file and save it as byte []
4. FileStream fs = new FileStream (imagepath, FileMode. Open );
5. byte [] byData = new byte [fs. Length];
6. fs. Read (byData, 0, byData. Length );
7. fs. Close ();
8. return byData;
9 .}
10.
2. If the parameter type is an Image object, the returned Byte [] type is:
1. public byte [] PhotoImageInsert (System. Drawing. Image imgPhoto)
2 .{
3. // convert the Image into streaming data and save it as byte []
4. MemoryStream mstream = new MemoryStream ();
5. imgPhoto. Save (mstream, System. Drawing. Imaging. ImageFormat. Bmp );
6. byte [] byData = new Byte [mstream. Length];
7. mstream. Position = 0;
8. mstream. Read (byData, 0, byData. Length );
9. mstream. Close ();
10. return byData;
11 .}
Now, we can convert the image into a Byte [] object through the above method, then, the object is saved to the database, and the binary format of the image is saved to the database. Next I will talk about how to read images from the database. In fact, this is the opposite process.
. NET binary image reading: Convert the corresponding fields into Byte []: Byte [] bt = (Byte []) XXXX
1. the parameter is of the Byte [] type, and the returned value is an Image object:
1. public System. Drawing. Image ReturnPhoto (byte [] streamByte)
2 .{
3. System. IO. MemoryStream MS = new System. IO. MemoryStream (streamByte );
4. System. Drawing. Image img = System. Drawing. Image. FromStream (MS );
5. return img;
6 .}
2. the parameter is of the Byte [] type and has no return value. This is for asp.net to output the image to the webpage (Response. BinaryWrite)
1. public void WritePhoto (byte [] streamByte)
2 .{
3. // The default value of Response. ContentType is "text/html"
4. Response. ContentType = "image/GIF ";
5. // image output types: image/GIF image/JPEG
6. Response. BinaryWrite (streamByte );
7 .}
Supplement:
For the value of Response. ContentType, in addition to the image type, there are other types:
1. Response. ContentType = "application/msword ";
2. Response. ContentType = "application/x-shockwave-flash ";
3. Response. ContentType = "application/vnd. ms-excel ";
In addition, different output types can be used for different formats:
1. switch (dataread ("document_type "))
2 .{
3. case "doc ":
4. Response. ContentType = "application/msword ";
5. case "swf ":
6. Response. ContentType = "application/x-shockwave-flash ";
7. case "xls ":
8. Response. ContentType = "application/vnd. ms-excel ";
9. case "gif ":
10. Response. ContentType = "image/gif ";
11. case "Jpg ":
12. Response. ContentType = "image/jpeg ";
13 .}
Protected void button#click (object sender, EventArgs e)
{
If (FileUpload1.HasFile)
{
Stream mystream = FileUpload1.PostedFile. InputStream; // FileUpload1 is the upload control ..
Int length = FileUpload1.PostedFile. ContentLength;
Byte [] bytes = new byte [length];
Mystream. Read (bytes, 0, length );
Mystream. Close ();
String conn = "server = (local); database = Image; Uid = SAS; Pwd = 123456 ";
SqlConnection myconn = new SqlConnection (conn );
Myconn. Open ();
String str = "insert into image (img) values ('" + bytes + "')";
SqlCommand mycomm = new SqlCommand (str, myconn );
Mycomm. ExecuteNonQuery ();
Myconn. Close ();
}
}
Save the image to the database...
Below is the picture read from the database...
Protected void Button2_Click (object sender, EventArgs e)
{
String imgtype = FileUpload1.PostedFile. ContentType;
String conn = "server = (local); database = Image; Uid = SAS; Pwd = 123456 ";
String str = "select img from image where ID = 5 ";
SqlConnection myconn = new SqlConnection (conn );
Myconn. Open ();
// SqlDataAdapter myda = new SqlDataAdapter (str, conn );
// DataSet myds = new DataSet ();
// Myda. Fill (myds );
SqlCommand mycom = new SqlCommand (str, myconn );
SqlDataReader mydr = mycom. ExecuteReader ();
If (mydr. Read ())
{
Response. ContentType = imgtype;
Response. BinaryWrite (byte []) mydr ["img"]);
}
Else
{
Response. Write ("image not read from database ");
}
Myconn. Close ();
}
I. background
C # And the new technical solution WEB Service are developed using a new language in the development of a new project. However, in the new project, some old modules need to be used, it is generally written in C, C ++, or Delphi. There are three available methods for developers to use the old module: first, rewrite the C or C ++ functions with C # completely, so that the entire project code is more unified and easy to maintain. However, although Microsoft and some books say how C # is close to C ++, it is still a very painful thing to rewrite, especially the pointer and memory operations in C ++; 2. encapsulate C or C ++ functions into COM. It is convenient to call COM in C, only the conversion between the C or C ++ type and the COM type needs to be processed during encapsulation, but it also has some trouble. In addition, the COM needs to be registered, which may cause confusion when the number of registrations is too large; 3. encapsulate C or C ++ functions into a dynamic link library. The encapsulation process is simple and does not work much. Therefore, I decided to use the method of loading the dynamic link library to implement it. As a result, the question of how to call a custom dynamic link library in C # emerged. I searched for related topics online, I found an article calling the system API, but it does not explain how to solve this problem, and there is no detailed description on MSDN. Based on this, I decided to start from a simple step by step to see if I could achieve my goal.
(Note: I am afraid of the trouble of rewriting here. The code I rewrite is a variable-length encryption algorithm function. There are more than 600 lines of code, and I am not familiar with the algorithm itself, there are too many pointer and memory operations in the algorithm. To ensure the algorithm is correct, the most feasible method is to move less code. Otherwise, as long as there is a slight error, it cannot be sure that the algorithm is compatible with the previous one)
Ii. Technical Implementation
Next let's take a look at how to gradually implement dynamic library loading and type Matching:
For the definition of function export in the dynamic link library, you can refer to the macro definition below:
# Define LIBEXPORT_API extern "C" _ declspec (dllexport)
The first step is to start with a simple call and define a simple function, which only implements an integer addition sum:
LIBEXPORT_API int mySum (int a, int B) {return a + B ;}
C # define the import definition:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. auto, CallingConvention = CallingConvention. stdCall)] public static extern int mySum (int a, int B );
}
Call the test in C:
Int iSum = RefComm. mySum (2, 3 );
Run the command and check that iSum is 5. The call is correct. The first step is the completion of the test. It indicates that the custom dynamic link library function can be called in C.
Step 2: I have defined the string operation function (for simplicity, the previous function name is used) and the returned result is a string:
LIBEXPORT_API char * mySum (char * a, char * B) {sprintf (B, "% s", a) return ;}
C # define the import definition:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. auto, CallingConvention = CallingConvention. stdCall)] public static extern string mySum (string a, string B );
}
Call the test in C:
String strDest = "";
String strTmp = RefComm. mySum ("12345", strDest );
The strTmp value is 12345, but the strDest value is null.
When I modify the dynamic link library implementation, the returned result is string B:
LIBEXPORT_API char * mySum (char * a, char * B) {sprintf (B, "% s", a) return B ;}
Modify C # import definition and change string B to ref mode:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. auto, CallingConvention = CallingConvention. stdCall)] public static extern string mySum (string a, ref string B );
}
Call the test again in C:
String strDest = "";
String strTmp = RefComm. mySum ("12345", ref strDest );
The strTmp and strDest operations are incorrect. They contain invisible characters.
Modify the C # import definition and change CharSet from Auto to Ansi:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. ansi, CallingConvention = CallingConvention. stdCall)] public static extern string mySum (string a, string B );
}
Call the test again in C:
String strDest = "";
String strTmp = RefComm. mySum ("12345", ref strDest );
The strTmp value is 12345, but the strDest value is not assigned. The second step implements the function return string, but the output fails in the function exit parameter.
Modify C # import definition again, and change string B to reference (ref ):
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. ansi, CallingConvention = CallingConvention. stdCall)] public static extern string mySum (string a, ref string B );
}
The call fails during running and cannot be continued.
Step 3: Modify the dynamic link library implementation and Change B to a double pointer:
LIBEXPORT_API char * mySum (char * a, char ** B) {sprintf (* B), "% s", a) return * B ;}
C # import definition:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. ansi, CallingConvention = CallingConvention. stdCall)] public static extern string mySum (string a, ref string B );
}
Call the test in C:
String strDest = "";
String strTmp = RefComm. mySum ("12345", ref strDest );
The strTmp and strDest values are "12345" in the running result. The call is correct. The third step outputs the correct output result of function exit parameters.
Step 4: Modify the dynamic link library implementation to output Integer Parameters:
LIBEXPORT_API int mySum (int a, int B, int * c) {* c = a + B; return * c ;}
C # import definition:
Public class RefComm
{
[DllImport ("LibEncrypt. dll ", EntryPoint =" mySum ", CharSet = CharSet. ansi, CallingConvention = CallingConvention. stdCall)] public static extern int mySum (int a, int B, ref int c );
}
Call the test in C:
Int c = 0;
Int iSum = RefComm. mySum (2, 3, ref c );
Run the command to check whether iSum and c are both 5. The call is correct.
After the experiments in the above steps, I have basically mastered how to define the dynamic library function and how to define the import in C #. With this foundation, I soon implemented the call of the variable-length encryption function in C, so far.
Iii. Conclusion
In C #, call C ++ to compile the dynamic link library function. to export the parameter output, use a pointer. For strings, use a double pointer, for the C # import definition, you need to use the reference (ref) definition.
For function return values, the C # import definition must be consistent with the C ++ dynamic library function Declaration definition. Otherwise, function call may fail.
When defining the import, pay attention to the CharSet and CallingConvention parameters. Otherwise, the call fails or the result is abnormal.
During running, the dynamic link library is placed in the directory of the C # program. Here I am a dynamic link library of C #, and the two dynamic link libraries are run in the same directory.
From the wanglei_smartfish Column