drupal hit counter
Jerry Huang | All posts by jerry

Jerry Huang apps and developing apps

How to export contacts from Gmail

16. April 2011 00:08 by Jerry in Smart Dial

1) logon with your gmail ID on www.gmail.com, and click "Contacts"

2)click "More actions" and select "Export"

3) Choose "All contacts" and "Outlook CSV" format. It's not a must, but if you choose Outlook format you will able to use the default "Windows Live" srouce type for data conversion later on. Then click "Export"

 

4) click "Save", done.

How to export your Live contacts

15. April 2011 23:52 by Jerry in Smart Dial

1) login www.hotmail.com with your Live ID, and then click "Contacts"

 

2) click "Manage" and choose "Export"

3) input the urgly stupid 8 digit characters as it shown, then click "Export"

 

4) wait for a while (sometimes it needs a few minutes if you have many contacts and your network connection happed to be slow), you will see a download dialog, click "Save" to store the folder to your computer, "My documents" would be a nice choice. Sorry for the screenshot has to be Chinese. I don't have an english Windows on hand. Probably a good start for learning Chinese, lol

Serializing image in WP7

15. April 2011 03:23 by Jerry in Windows Phone Development

This post is to celebrate my 2nd app - Smart Dial has been approved in marketplace.

None of the build in imaging classes in Windows Phone or Silverlight is serializable, that's why I have to build my own class.Cool

To serialize a custom object, the class need to implement IXmlSerializable interface. So my class inherits BitmapSource and then implement IXmlSerializable.

The idea of the whole thing is actually pretty simple. Just covert the image into byte array, and then transform to Base64 string, and backward for deserialization. With such approach, we are able to ship the image within XML(i.e. pure text). This is how my app (Smart Dial) to transfer contact photos between WP7 and server.

 Since my Smart Dial solution consists 2 client programs in handset device and desktop computer, I made the class compatible with both silverlight (WP7) and Winform (base on .Net 3.5). However, somehow I can't load the image source to itself in winform version. The BitmapSource in winform doesn't contain the SetSource method, I have use a stupid property (Source).

Simply copy and paste and compile and enjoyLaughing

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Windows;
using System.Xml.Serialization;
using System.IO;
using System.Windows.Media.Imaging;
using System.Xml.Schema;
using System.Xml;#if !SILVERLIGHT
using System.Drawing;
#endif
namespace SmartDial.Data
{public class SerializableImage : BitmapSource, IXmlSerializable{#if SILVERLIGHTprivate string ImageToString(BitmapSource image)
#elseprivate string ImageToString(Bitmap image)
#endif{byte[] byteArray;using (MemoryStream stream = new MemoryStream()){#if SILVERLIGHTWriteableBitmap bmp = new WriteableBitmap((BitmapSource)image);bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);byteArray = stream.ToArray();
#elseimage.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);stream.Flush();byteArray = stream.ToArray();
#endif}return Convert.ToBase64String(byteArray);}public SerializableImage() { }#if SILVERLIGHTpublic SerializableImage(Uri uri){using (Stream stream = Application.GetResourceStream(uri).Stream){this.SetSource(stream);}}#elsepublic SerializableImage(Image image){this.Source = (Bitmap)image;}protected override Freezable CreateInstanceCore() { return new SerializableImage(); }public Bitmap Source { get;  set; }
#endifprivate void StringToImage(string imageString){if (imageString == null)throw new ArgumentNullException("imageString");byte[] array = Convert.FromBase64String(imageString);#if SILVERLIGHTthis.SetSource (new MemoryStream(array));
#elseSource = (Bitmap)Image.FromStream(new MemoryStream(array));
#endif}#region IXmlSerializable Memberspublic XmlSchema GetSchema(){throw new NotImplementedException();}public void ReadXml(XmlReader reader){if (reader.IsEmptyElement || !reader.Read()){return;}XmlSerializer imgSerializer = new XmlSerializer(typeof(string));while (reader.NodeType != XmlNodeType.EndElement){reader.ReadStartElement("SerializedImage");string img = (string)imgSerializer.Deserialize(reader);reader.ReadEndElement();reader.MoveToContent();StringToImage(img);}reader.ReadEndElement();}public void WriteXml(XmlWriter writer){XmlSerializer imgSerializer = new XmlSerializer(typeof(string));writer.WriteStartElement("SerializedImage");#if SILVERLIGHTstring img = ImageToString( this);
#elsestring img = ImageToString(this.Source);
#endifimgSerializer.Serialize(writer, img);writer.WriteEndElement();}#endregion}
}

HD2: a tour to TOILET

9. April 2011 12:10 by Jerry in

the victim, naked...

the murderer, he is keep committing to crimes afterward BTW

still alive...yea, I knew, thanks to DFT...

coming back...

faith regained.

new feature in v1.4

6. April 2011 03:03 by Jerry in IP CAM

The new 1.4 version ships with a feature: upload / download your camera config files to/from server.

In the Setup screen, click the expand button at application bar (the "..." at right down corner), then click the "upload/download camera", enjoy! Laughing

My first app on Windows Marketplace now

17. March 2011 20:21 by Jerry in IP CAM

Finally, my first Windows Phone 7 application published!Laughing 

Search "ip cam control" in the Marketplace with your Windows Phone device!!

At the end of below page, I provided a windows version to test if my app compatible with your camera. Please have a try if you are interested.

more detail...

 

DbMoto comments and experience

3. September 2010 13:00 by Jerry in Product Experience

The previous blog I wrote last night is something about DbMoto. Today I found that my feeling is a bit more than that, so I list out the summary how I feel after using this product.

  1. It’s basically a good tool for syncalizing data from DB2 to SQL, in my case. Easy to setup and use comparing with some jumbo products. It provides a nice GUI tool to setup and manage replications.
  2. Not very good for real time change data capture, currently we set the interval to 30 minutes, i.e. data will sync from DB2 to SQL every 30 minutes. There was a time we set to 5 minute but it seems there were some problems. I am not sure about the detail (I'm not in the AS400 team), what I heard fromt my colleague is that the receiver in AS400 caused the CPU overran.
  3. The product and the company have a long history and the market share is growing. The support is ok; so far they solved all problems we hit, as I can remember.
  4. I believe the engine is base on .Net framework 2.0, so it needs to run on a Windows server. This is ok for us but some people insist the performance is better if a product is base on non-Microsoft server.
  5. Very good extensibility, we can write our own script into the replication. We are using VB.NET as script language, but I guess it also supports other .NET languages. The script will be compiled to .NET binary code so the efficiency will be better than those dynamically compile.
  6. Scripting is good but also brings the biggest problem – there is no way to debug the script in development. What we are doing now, is to write log for debugging. For development, ideally we hope the dbmoto engine somehow can call into Visual Studio so that we may set breakpoint, watch the value of local variables, etc. Due to this, we avoid to put something too complicated in the scripts.

Overall, I will say dbmoto is a light-weight to medium change data capture engine, to keep 2 different databases identical. If your requirement is not about some sort of comprehensive ETL solution, just to sync data from one place to another, DbMoto should be a good tool for that. However, it might not suit for you if require extremely low latency (i.e real time) syncalization. Hmmm, but real-time is a big challenge for all products.

The more stupid you assume the consumer is, the better implementation your framework would be

2. September 2010 23:29 by Jerry in Framework Design

DbMoto is a light-weight to medium change data capture product in my opinion. It basically sync data from one database to another, to keep 2 database identical, even target and source are not the same kind of database (from DB2 to SQL for example).

One of the strengths of DbMoto is that you can write your own script in a replication, so that it could satisfy some complicated business needs. In my case, we used VB.NET as the scripting language. Recently we found some error about deadlock in the log. Originally we thought the problem was from SQL database, but we couldn't find any log entry in SQL server. We fired a ticket for vendor support. Later on they told us to use SyncLock on the TargetConnection object. So I change the script to use Monitor (better than SyncLock) instead. The code goes like:

Code
1
2
3
4
5
6
7
8
9
10
11
 TrySystem.Threading.Monitor.Enter(TargetConnection)cmd = TargetConnection.CreateCommand...Catch e As Exception...FinallySystem.Threading.Monitor.Exit(TargetConnection)End Try

From this accident, I feel this should be a minor problem in the architecture of DbMoto, that's how the title came into my mind. In short, the object provided by Dbmoto is not thread-safe. From the point of view of framework design, when writing something will be used in multi-threads environment, it's better to make sure the objects that explosing to consumer are thread-safe. Rather than leaving the problem to sub-classes, why not just handle them internally?

scan barcode from TIFF

31. July 2010 09:25 by Jerry in Cool stuff

http://www.codeproject.com/KB/graphics/BarcodeImaging3.aspx

The ariticle above is really something awesome, you may easily scan barcode in an image, pure managed code. It supports Code39, Code39ex, Code128, EAN, EAN-2, EAN-5.

Together with below utility class, I used it in an application to scan barcode from tiff

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;using System.Collections;namespace AMA.Util
{/// <summary>/// Summary description for TiffManager./// </summary>public class TiffManager : IDisposable{private string _ImageFileName;private int _PageNumber;private Image image;private string _TempWorkingDir;public TiffManager(string imageFileName){this._ImageFileName=imageFileName;image=Image.FromFile(_ImageFileName);GetPageNumber();}public TiffManager(){}/// <summary>/// Read the image file for the page number./// </summary>private void GetPageNumber(){Guid objGuid=image.FrameDimensionsList[0];FrameDimension objDimension=new FrameDimension(objGuid);//Gets the total number of frames in the .tiff file_PageNumber=image.GetFrameCount(objDimension);return;}/// <summary>/// Read the image base string,/// Assert(GetFileNameStartString(@"c:\test\abc.tif"),"abc")/// </summary>/// <param name="strFullName"></param>/// <returns></returns>private string GetFileNameStartString(string strFullName){int posDot=_ImageFileName.LastIndexOf(".");int posSlash=_ImageFileName.LastIndexOf(@"\");return _ImageFileName.Substring(posSlash+1,posDot-posSlash-1);}/// <summary>/// This function will output the image to a TIFF file with specific compression format/// </summary>/// <param name="outPutDirectory">The splited images' directory</param>/// <param name="format">The codec for compressing</param>/// <returns>splited file name array list</returns>public ArrayList SplitTiffImage(string outPutDirectory,EncoderValue format){string fileStartString=outPutDirectory+"<a href="file://\\"+GetFileNameStartString(_ImageFileName">\\"+GetFileNameStartString(_ImageFileName</a>);ArrayList splitedFileNames=new ArrayList();try{Guid objGuid=image.FrameDimensionsList[0];FrameDimension objDimension=new FrameDimension(objGuid);//Saves every frame as a separate file.Encoder enc=Encoder.Compression;int curFrame=0;for (int i=0;i<_PageNumber;i++){image.SelectActiveFrame(objDimension,curFrame);EncoderParameters ep=new EncoderParameters(1);ep.Param[0]=new EncoderParameter(enc,(long)format);ImageCodecInfo info=GetEncoderInfo("image/tiff");//Save the master bitmapstring fileName=string.Format("{0}{1}.TIF",fileStartString,i.ToString());image.Save(fileName,info,ep);splitedFileNames.Add(fileName);curFrame++;} }catch (Exception){throw;}return splitedFileNames;}/// <summary>/// This function will join the TIFF file with a specific compression format/// </summary>/// <param name="imageFiles">string array with source image files</param>/// <param name="outFile">target TIFF file to be produced</param>/// <param name="compressEncoder">compression codec enum</param>public void JoinTiffImages(string[] imageFiles,string outFile,EncoderValue compressEncoder){try{//If only one page in the collection, copy it directly to the target file.if (imageFiles.Length==1){File.Copy(imageFiles[0],outFile,true);return;}//use the save encoderEncoder enc=Encoder.SaveFlag;EncoderParameters ep=new EncoderParameters(2);ep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.MultiFrame); ep.Param[1] = new EncoderParameter(Encoder.Compression,(long)compressEncoder);Bitmap pages=null;int frame=0;ImageCodecInfo info=GetEncoderInfo("image/tiff");foreach(string strImageFile in imageFiles){if(frame==0){pages=(Bitmap)Image.FromFile(strImageFile);//save the first framepages.Save(outFile,info,ep);}else{//save the intermediate framesep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.FrameDimensionPage);Bitmap bm=(Bitmap)Image.FromFile(strImageFile);pages.SaveAdd(bm,ep);} if(frame==imageFiles.Length-1){//flush and close.ep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.Flush);pages.SaveAdd(ep);}frame++;}}catch (Exception){throw;}return;}/// <summary>/// This function will join the TIFF file with a specific compression format/// </summary>/// <param name="imageFiles">array list with source image files</param>/// <param name="outFile">target TIFF file to be produced</param>/// <param name="compressEncoder">compression codec enum</param>public void JoinTiffImages(ArrayList imageFiles,string outFile,EncoderValue compressEncoder){try{//If only one page in the collection, copy it directly to the target file.if (imageFiles.Count==1){File.Copy((string)imageFiles[0],outFile,true);return;}//use the save encoderEncoder enc=Encoder.SaveFlag;EncoderParameters ep=new EncoderParameters(2);ep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.MultiFrame); ep.Param[1] = new EncoderParameter(Encoder.Compression,(long)compressEncoder);Bitmap pages=null;int frame=0;ImageCodecInfo info=GetEncoderInfo("image/tiff");foreach(string strImageFile in imageFiles){if(frame==0){pages=(Bitmap)Image.FromFile(strImageFile);//save the first framepages.Save(outFile,info,ep);}else{//save the intermediate framesep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.FrameDimensionPage);Bitmap bm=(Bitmap)Image.FromFile(strImageFile);pages.SaveAdd(bm,ep);bm.Dispose();} if(frame==imageFiles.Count-1){//flush and close.ep.Param[0]=new EncoderParameter(enc,(long)EncoderValue.Flush);pages.SaveAdd(ep);}frame++;}}catch (Exception ex){
#if DEBUGConsole.WriteLine(ex.Message);
#endifthrow;}return;}/// <summary>/// Remove a specific page within the image object and save the result to an output image file./// </summary>/// <param name="pageNumber">page number to be removed</param>/// <param name="compressEncoder">compress encoder after operation</param>/// <param name="strFileName">filename to be outputed</param>/// <returns></</returns>public void RemoveAPage(int pageNumber,EncoderValue compressEncoder,string strFileName){try{//Split the image files to single pages.ArrayList arrSplited=SplitTiffImage(this._TempWorkingDir,compressEncoder);//Remove the specific page from the collectionstring strPageRemove=string.Format("{0}\\{1}{2}.TIF",_TempWorkingDir,GetFileNameStartString(this._ImageFileName),pageNumber);arrSplited.Remove(strPageRemove);JoinTiffImages(arrSplited,strFileName,compressEncoder);}catch(Exception){throw;}return;}/// <summary>/// Getting the supported codec info./// </summary>/// <param name="mimeType">description of mime type</param>/// <returns>image codec info</returns>private ImageCodecInfo GetEncoderInfo(string mimeType){ImageCodecInfo[] encoders=ImageCodecInfo.GetImageEncoders();for (int j=0;j<encoders.Length;j++){if (encoders[j].MimeType==mimeType)return encoders[j];}throw new Exception( mimeType + " mime type not found in ImageCodecInfo" );}/// <summary>/// Return the memory steam of a specific page/// </summary>/// <param name="pageNumber">page number to be extracted</param>/// <returns>image object</returns>public Image GetSpecificPage(int pageNumber){MemoryStream ms=null;Image retImage=null;try{ms=new MemoryStream();Guid objGuid=image.FrameDimensionsList[0];FrameDimension objDimension=new FrameDimension(objGuid);image.SelectActiveFrame(objDimension,pageNumber);image.Save(ms,ImageFormat.Bmp);retImage=Image.FromStream(ms);return retImage;}catch (Exception){ms.Close();retImage.Dispose();throw;}}/// <summary>/// Convert the existing TIFF to a different codec format/// </summary>/// <param name="compressEncoder"></param>/// <returns></returns>public void ConvertTiffFormat(string strNewImageFileName,EncoderValue compressEncoder){//Split the image files to single pages.ArrayList arrSplited=SplitTiffImage(this._TempWorkingDir,compressEncoder);JoinTiffImages(arrSplited,strNewImageFileName,compressEncoder);return;}/// <summary>/// Image file to operate/// </summary>public string ImageFileName{get{return _ImageFileName;}set{_ImageFileName=value;}}/// <summary>/// Buffering directory/// </summary>public string TempWorkingDir{get{return _TempWorkingDir;}set{_TempWorkingDir=value;}}/// <summary>/// Image page number/// </summary>public int PageNumber{get{return _PageNumber;}}#region IDisposable Memberspublic void Dispose(){image.Dispose();System.GC.SuppressFinalize(this);}#endregion}
}