1+ using Newtonsoft . Json ;
12using System ;
23using System . Text ;
34using System . Net ;
45using System . IO ;
5- using System . Collections . Generic ;
66
7- namespace VisualSearchUpload
8- {
7+ /* This sample makes a call to the Bing Visual Search API with a query image and returns similar images with details.
8+ * Bing Visual Search API:
9+ * https://docs.microsoft.com/en-us/rest/api/cognitiveservices/bingvisualsearch/images/visualsearch
10+ */
911
12+ namespace BingVisualSearch
13+ {
1014 class Program
1115 {
12- // **********************************************
13- // *** Update and verify the following values. ***
14- // **********************************************
15-
16- // Add your Azure Bing Search V7 subscription key to your environment variables.
17- const string accessKey = Environment . GetEnvironmentVariable ( "BING_SEARCH_V7_SUBSCRIPTION_KEY" ) ;
18- // Add your Azure Bing Search V7 endpoint to your environment variables.
19- const string uriBase = Environment . GetEnvironmentVariable ( "BING_SEARCH_V7_ENDPOINT" ) + "/bing/v7.0/images/visualsearch" ;
16+ // Add your Azure Bing Search V7 subscription key and endpoint to your environment variables.
17+ static string subscriptionKey = Environment . GetEnvironmentVariable ( "BING_SEARCH_V7_SUBSCRIPTION_KEY" ) ;
18+ static string endpoint = Environment . GetEnvironmentVariable ( "BING_SEARCH_V7_ENDPOINT" ) + "/bing/v7.0/images/visualsearch" ;
2019
2120 // Set the path to the image that you want to get insights of.
22- static string imagePath = @"<pathtoimagegoeshere> " ;
21+ static string imagePath = @"objects.jpg " ;
2322
2423 // Boundary strings for form data in body of POST.
2524 const string CRLF = "\r \n " ;
@@ -28,216 +27,63 @@ class Program
2827 static string EndBoundaryTemplate = "--{0}--" ;
2928
3029 const string CONTENT_TYPE_HEADER_PARAMS = "multipart/form-data; boundary={0}" ;
31- const string POST_BODY_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\" image\" ; filename=\" {0}\" " + CRLF + CRLF ;
30+ const string POST_BODY_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\" image\" ; filename=\" {0}\" " + CRLF + CRLF ;
3231
3332
3433 static void Main ( )
3534 {
3635 try
3736 {
38- Console . OutputEncoding = System . Text . Encoding . UTF8 ;
39-
40- if ( accessKey . Length == 32 )
41- {
42- if ( IsImagePathSet ( imagePath ) )
43- {
44- var filename = GetImageFileName ( imagePath ) ;
45- Console . WriteLine ( "Getting image insights for image: " + filename ) ;
46- var imageBinary = GetImageBinary ( imagePath ) ;
47-
48- // Set up POST body.
49- var boundary = string . Format ( BoundaryTemplate , Guid . NewGuid ( ) ) ;
50- var startFormData = BuildFormDataStart ( boundary , filename ) ;
51- var endFormData = BuildFormDataEnd ( boundary ) ;
52- var contentTypeHdrValue = string . Format ( CONTENT_TYPE_HEADER_PARAMS , boundary ) ;
53-
54- var json = BingImageSearch ( startFormData , endFormData , imageBinary , contentTypeHdrValue ) ;
55-
56- Console . WriteLine ( "\n JSON Response:\n " ) ;
57- Console . WriteLine ( JsonPrettyPrint ( json ) ) ;
58- }
59- }
60- else
37+ Console . OutputEncoding = Encoding . UTF8 ;
38+
39+ // Gets image.
40+ var filename = new FileInfo ( imagePath ) . FullName ;
41+ Console . WriteLine ( "Getting image insights for image: " + Path . GetFileName ( filename ) ) ;
42+ var imageBinary = File . ReadAllBytes ( imagePath ) ;
43+
44+ // Sets up POST body.
45+ var boundary = string . Format ( BoundaryTemplate , Guid . NewGuid ( ) ) ;
46+
47+ // Builds form start data.
48+ var startBoundary = string . Format ( StartBoundaryTemplate , boundary ) ;
49+ var startFormData = startBoundary + CRLF ;
50+ startFormData += string . Format ( POST_BODY_DISPOSITION_HEADER , filename ) ;
51+
52+ // Builds form end data.
53+ var endFormData = CRLF + CRLF + string . Format ( EndBoundaryTemplate , boundary ) + CRLF ;
54+ var contentTypeHeaderValue = string . Format ( CONTENT_TYPE_HEADER_PARAMS , boundary ) ;
55+
56+ // Sets up the request for a visual search.
57+ WebRequest request = HttpWebRequest . Create ( endpoint ) ;
58+ request . ContentType = contentTypeHeaderValue ;
59+ request . Headers [ "Ocp-Apim-Subscription-Key" ] = subscriptionKey ;
60+ request . Method = "POST" ;
61+
62+ // Writes the boundary and Content-Disposition header, then writes
63+ // the image binary, and finishes by writing the closing boundary.
64+ using ( Stream requestStream = request . GetRequestStream ( ) )
6165 {
62- Console . WriteLine ( "Invalid Bing Visual Search API subscription key!" ) ;
63- Console . WriteLine ( "Please paste yours into the source code." ) ;
66+ StreamWriter writer = new StreamWriter ( requestStream ) ;
67+ writer . Write ( startFormData ) ;
68+ writer . Flush ( ) ;
69+ requestStream . Write ( imageBinary , 0 , imageBinary . Length ) ;
70+ writer . Write ( endFormData ) ;
71+ writer . Flush ( ) ;
72+ writer . Close ( ) ;
6473 }
6574
66- Console . Write ( "\n Press Enter to exit " ) ;
67- Console . ReadLine ( ) ;
75+ // Calls the Bing Visual Search endpoint and returns the JSON response.
76+ HttpWebResponse response = ( HttpWebResponse ) request . GetResponseAsync ( ) . Result ;
77+ string json = new StreamReader ( response . GetResponseStream ( ) ) . ReadToEnd ( ) ;
78+
79+ Console . WriteLine ( "\n JSON Response:\n " ) ;
80+ dynamic parsedJson = JsonConvert . DeserializeObject ( json ) ;
81+ Console . WriteLine ( JsonConvert . SerializeObject ( parsedJson , Formatting . Indented ) ) ;
6882 }
6983 catch ( Exception e )
7084 {
7185 Console . WriteLine ( e . Message ) ;
7286 }
7387 }
74-
75-
76-
77- /// <summary>
78- /// Verify that imagePath exists.
79- /// </summary>
80- static Boolean IsImagePathSet ( string path )
81- {
82- if ( string . IsNullOrEmpty ( path ) )
83- throw new ArgumentException ( "Image path is null or empty." ) ;
84-
85- if ( ! File . Exists ( path ) )
86- throw new ArgumentException ( "Image path does not exist." ) ;
87-
88- var size = new FileInfo ( path ) . Length ;
89-
90- if ( size > 1000000 )
91- throw new ArgumentException ( "Image is greater than the 1 MB maximum size." ) ;
92-
93- return true ;
94- }
95-
96-
97-
98- /// <summary>
99- /// Get the binary characters of an image.
100- /// </summary>
101- static byte [ ] GetImageBinary ( string path )
102- {
103- return File . ReadAllBytes ( path ) ;
104- }
105-
106-
107- /// <summary>
108- /// Get the image's filename.
109- /// </summary>
110- static string GetImageFileName ( string path )
111- {
112- return new FileInfo ( path ) . Name ;
113- }
114-
115-
116- /// <summary>
117- /// Build the beginning part of the form data.
118- /// </summary>
119- static string BuildFormDataStart ( string boundary , string filename )
120- {
121- var startBoundary = string . Format ( StartBoundaryTemplate , boundary ) ;
122-
123- var requestBody = startBoundary + CRLF ;
124- requestBody += string . Format ( POST_BODY_DISPOSITION_HEADER , filename ) ;
125-
126- return requestBody ;
127- }
128-
129-
130- /// <summary>
131- /// Build the ending part of the form data.
132- /// </summary>
133- static string BuildFormDataEnd ( string boundary )
134- {
135- return CRLF + CRLF + string . Format ( EndBoundaryTemplate , boundary ) + CRLF ;
136- }
137-
138-
139-
140- /// <summary>
141- /// Calls the Bing visual search endpoint and returns the JSON response.
142- /// </summary>
143- static string BingImageSearch ( string startFormData , string endFormData , byte [ ] image , string contentTypeValue )
144- {
145- WebRequest request = HttpWebRequest . Create ( uriBase ) ;
146- request . ContentType = contentTypeValue ;
147- request . Headers [ "Ocp-Apim-Subscription-Key" ] = accessKey ;
148- request . Method = "POST" ;
149-
150- // Writes the boundary and Content-Disposition header, then writes
151- // the image binary, and finishes by writing the closing boundary.
152- using ( Stream requestStream = request . GetRequestStream ( ) )
153- {
154- StreamWriter writer = new StreamWriter ( requestStream ) ;
155- writer . Write ( startFormData ) ;
156- writer . Flush ( ) ;
157- requestStream . Write ( image , 0 , image . Length ) ;
158- writer . Write ( endFormData ) ;
159- writer . Flush ( ) ;
160- writer . Close ( ) ;
161- }
162-
163-
164- HttpWebResponse response = ( HttpWebResponse ) request . GetResponseAsync ( ) . Result ;
165- string json = new StreamReader ( response . GetResponseStream ( ) ) . ReadToEnd ( ) ;
166-
167- return json ;
168- }
169-
170-
171- /// <summary>
172- /// Formats the given JSON string by adding line breaks and indents.
173- /// </summary>
174- /// <param name="json">The raw JSON string to format.</param>
175- /// <returns>The formatted JSON string.</returns>
176- static string JsonPrettyPrint ( string json )
177- {
178- if ( string . IsNullOrEmpty ( json ) )
179- return string . Empty ;
180-
181- json = json . Replace ( Environment . NewLine , "" ) . Replace ( "\t " , "" ) ;
182-
183- StringBuilder sb = new StringBuilder ( ) ;
184- bool quote = false ;
185- bool ignore = false ;
186- char last = ' ' ;
187- int offset = 0 ;
188- int indentLength = 2 ;
189-
190- foreach ( char ch in json )
191- {
192- switch ( ch )
193- {
194- case '"' :
195- if ( ! ignore ) quote = ! quote ;
196- break ;
197- case '\\ ' :
198- if ( quote && last != '\\ ' ) ignore = true ;
199- break ;
200- }
201-
202- if ( quote )
203- {
204- sb . Append ( ch ) ;
205- if ( last == '\\ ' && ignore ) ignore = false ;
206- }
207- else
208- {
209- switch ( ch )
210- {
211- case '{' :
212- case '[' :
213- sb . Append ( ch ) ;
214- sb . Append ( Environment . NewLine ) ;
215- sb . Append ( new string ( ' ' , ++ offset * indentLength ) ) ;
216- break ;
217- case '}' :
218- case ']' :
219- sb . Append ( Environment . NewLine ) ;
220- sb . Append ( new string ( ' ' , -- offset * indentLength ) ) ;
221- sb . Append ( ch ) ;
222- break ;
223- case ',' :
224- sb . Append ( ch ) ;
225- sb . Append ( Environment . NewLine ) ;
226- sb . Append ( new string ( ' ' , offset * indentLength ) ) ;
227- break ;
228- case ':' :
229- sb . Append ( ch ) ;
230- sb . Append ( ' ' ) ;
231- break ;
232- default :
233- if ( quote || ch != ' ' ) sb . Append ( ch ) ;
234- break ;
235- }
236- }
237- last = ch ;
238- }
239-
240- return sb . ToString ( ) . Trim ( ) ;
241- }
24288 }
24389}
0 commit comments