Content on this page
|
ApplicationProgram |
|
Set the Image Target |
|
Obtain source Image |
|
Execute Processing |
|
Zoom bitmap |
|
Manage dimensions |
|
Set background color |
|
Preview an image |
|
Show progress |
|
Solve the deadlock problem |
|
Completed Program |
|
Automatic PlayStation portable detection |
|
Drag and Drop Image Transmission |
|
Automatic horizontal/Vertical Rotation |
Smartphone, Pocket PC, and Sony PlayStation Portable are very useful image carrying devices. However, today's cameras are much more demanding than mobile devices. High pixels make the image print or preview on a large display very good, but it is not easy to achieve this effect when the display is small. These high-resolution image files take a long time to load and occupy a large amount of file space. (This article contains links to English websites) Many graphics programs, such as Microsoft Digital Image Pro 10, have the batch editing feature, allowing you to resize images in batches. If you have a portable media center, you can use Media Player 10 to resize an image during transmission. However, what you really need is a program that allows you to resize images and transmit them immediately. So I wrote a program and we can look at how it works. Whether you just want to use this program or want to studyCodeIs easy to get started. If you just want to use this program, I provide a user manual. Use applicationsI created this project using Visual C #2005 express edition. Open the corresponding project file to use. If you do not have Visual Studio, you can get a free copy from the http://msdn.microsoft.com/vstudio/express/visualcsharp. The initial download copy is very small, but the installation time code will reach 300 MB. After Visual Studio is installed on your machine, you can open the corresponding directory and select a solution file. In the following section, we will detail each part of the program. Examples andSource codeThey are not exactly the same, but we hope to focus on the important aspects of each development part. Back to Top Set the Image Target I useFolderbrowserdialogTo set the target. This allows you to find the target directory for transferring image files. I set this option to enable users to create a new directory for storing images: Outputdirdialog = new system. Windows. Forms. folderbrowserdialog (); outputdirdialog. Description = "select target"; outputdirdialog. shownewfolderbutton = true; outputdirdialog. showdialog (); I useShowdialogSo that when you use the following dialog box to select a target, the rest of the program can be paused: Figure 1: browsing target When you open the "my computer" tree, you can see all drive letters, including all drive letters of the storage device. Note: This program must also handle the situation where the user clicks the "cancel" button instead of selecting a folder. In this case, the generated path length will be 0, so we will display the corresponding message: If (outputdirdialog. selectedpath. Length = 0) {statuslabel. Text = "no target selected"; return ;} We use a label at the bottom of the table to send messages to users. Back to Top Obtain source Image After learning the location of the file, we need to select some files for transmission.OpenfiledialogThis operation happens because you can configure it to allow users to select multiple files. This dialog box also displays thumbnails of each image, so you can easily view the file to be transmitted. Sourcefilesdialog = new openfiledialog (); sourcefilesdialog. multiselect = true; sourcefilesdialog. Title = "select the file to be shrunk "; This Code creates this dialog box and configures it to allow multiple files to be selected. Now we can configure it to display only the image files to be transmitted: Sourcefilesdialog. filter = "image file (*. BMP ;*. JPG ;*. GIF) | *. BMP ;*. JPG ;*. GIF | all files (*. *) | *. *"; The filter string looks quite complex, but is actually very simple. Each element in a string is separated by a vertical line. Each filter is represented as a pair of items, a description string followed by a column of filter expressions. It looks clearer if the expression is as follows: "Image file (*. BMP ;*. JPG ;*. GIF) | *. BMP ;*. JPG ;*. GIF | "+" all files (*. *) | *. *" The filter above allows you to select bitmap, JPEG, or GIF image files. The second exercise user can select all files. For each line, the text to be displayed in front of the user is separated from the file extension column applied to the selected line. If you select the filter above, only the file names matching bitmap, JPEG, or GIF images are displayed. If the following filter is selected, all files are displayed. Figure 2: Filter Used Note: Only because the file has a special extension does not indicate that the file contains a special file type. Our program must ensure that invalid file content will not cause problems. We can introduce this part later. You can select any number of files from the directory, or even use Ctrl + A to select all files. When you click the OPEN button, the dialog box ends and you can process the file and transfer it to the target device. Back to Top Execute Processing OpenfiledialogReturns the Object Name of a column as a string array. Now, the program must open each file, load the bitmap in the file, adjust the bitmap size to the desired size, and then save the bitmap to the target directory. MethodProcessfilesAll the preceding operations can be performed. Processfiles (sourcefilesdialog. filenames, outputdirdialog. selectedpath );
This method will pass an array of file names and the target path for output. Then, it must process all the files in the same way, and scale and save each file in sequence. Private void processfiles (string [] filenames, string outputpath) {bitmap DEST = new Bitmap (size. width, size. height); foreach (string filename in filenames) {bitmap image; try {image = new Bitmap (filename);} catch {MessageBox. show ("An error occurred while loading the bitmap:" + filename); continue;} scalebitmap (DEST, image); string destfilename = outputpath + @ "\" + system. io. path. getfilenamewithoutextension (filename) + ". jpg "; try {DeST. save (destfilename, system. drawing. imaging. imageformat. JPEG);} catch {MessageBox. show ("An error occurred while saving the bitmap:" + destfilename); Return ;}}}
This method processes each file, creates a bitmap for each file, and callsScalebitmapMethod to scale the bitmap, and save the result back to the disk. Note: I have applied an exception handler to the bitmap of the created file. If loading fails, a message is displayed and the method starts to process the next image. A try catch structure is also applied to the Save operation. However, if this operation fails, the next operation may fail because the output device may be full. Therefore, if the Save call fails, the method will return instead of continuing. Back to Top Zoom bitmap It is very easy to scale the bitmap. You can use some plotting methods to draw a rectangle from one image to another. By controlling the size of the source and target, we can adjust the image size to make it suitable for our devices. The only difficulty is that we have to process the aspect ratio of the source and target images so that we do not cut out any part of the image. This is exactly the same as the problem when you watch an old TV program on a wide-screen TV (or watch a new TV program on a narrow-screen TV. The resize method must match the screen size and insert a blank area around the screen as needed. Private rectangle srcrect = new rectangle (); Private rectangle destrect = new rectangle (); Private void scalebitmap (Bitmap DEST, bitmap SRC) {destrect. width = DeST. width; destrect. height = DeST. height; using (Graphics G = graphics. fromimage (DEST) {brush B = new solidbrush (backgroundcolor); G. fillrectangle (B, destrect); srcrect. width = SRC. width; srcrect. height = SRC. height; float sourceaspect = (float) SRC. width/(float) SRC. height; float destaspect = (float) DeST. width/(float) DeST. height; If (sourceaspect> destaspect) {// when the width is greater than the height, keep the width unchanged and increase the height according to the proportion (note: the programmer comment in the example program file uses English, this document translates it into Chinese for reference.) destrect. width = DeST. width; destrect. height = (INT) (float) DeST. width/sourceaspect); destrect. X = 0; destrect. y = (DEST. height-destrect. height)/2;} when the else {// height is greater than the width, the height remains unchanged and the width is increased proportionally. height = DeST. height; destrect. width = (INT) (float) DeST. height * sourceaspect); destrect. X = (DEST. width-destrect. width)/2; destrect. y = 0;} G. drawimage (SRC, destrect, srcrect, system. drawing. graphicsunit. pixel );}} Adjusting the image size is actually very simple. You can provide the source and target rectanglesDrawimageMethod. The above method determines which method to scale the source rectangle and then adjusts the target rectangle to a proper size and position. MethodDrawimageIs part of the actual work. Note: The rectangle we use to adjust the source and target sizes is declared outside the method. In this way, we will not stop creating or deleting new rectangles for each scaled image. What we really need to do is to change the size of these rectangles each time, so we don't have to always create new rectangles. Back to Top Manage dimensions You need to select a range of possible widths and heights based on the target device. The best screen component to perform this operation isComboBoxThis component has a project list from which you can select a project. Figure 3: select the output format The best way to manage the output format is to create a special class to save the size information. Then, we can provide this type of instance arrayComboBoxYou can select an instance. Public class outputsize {public int width; Public int height; string name; Public override string tostring () {return name + "" + width. tostring () + "X" + height. tostring () ;}public outputsize (string inname, int inwidth, int inheight) {name = inname; width = inwidth; Height = inheight ;}}
OutputsizeThe type includes the name attribute used to identify the type and the height and width values. It providesTostringThe method is used to provideComboBox. Set the width and height attributes to public so that the methods in other classes can use these attributes. Finally, it uses a constructor so that we can set all values. Now, we can create an instance array for this class, which can be used to configureComboBox: Private outputsize [] resolutionsettings = new outputsize [] {New outputsize ("Pocket PC", 640,480), new outputsize ("qvga", 320,240), new outputsize ("PSP ", 480,272), new outputsize ("Smartphone", 176,180 )};
If you want to add other dimensions to the program, these dimensions can be placed in the array and automatically selected and used. Add settingsComboBoxIs very convenient: Resolutioncombobox. datasource = resolutionsettings; This is a very powerful function of Windows Forms.ComboBoxYou can introduce these settings and use the values in the array to fill in its selection. To obtain an existing selection, we only need to obtain the selection and convert it to the actual type we have recognized: Outputsize size = resolutioncombobox. selecteditem as outputsize; Now, we can useSizeInstanceWidthAndHeightAttribute to control scaling. Back to Top Set background colorWhen the aspect ratio of the image is not very timely, you can choose to fill the background color around the image. The color will be stored as a form member: Private color backgroundcolor = color. White; The background color is initially set to white, but you can select other colors based on your preferences. I useColordialogDialog Box to allow users to perform this operation: Backcolordialog = new colordialog (); backcolordialog. solidcoloronly = true; backcolordialog. Color = backgroundcolor; backcolordialog. showdialog (); This dialog box allows you to select a color: Figure 4: select a color After you select a color, you can use it as the background of the image (ScalebitmapMethod ). Back to Top Preview an image You may want to view the previewed image when transferring the image. UsePictureboxYou can easily view the components. We willPictureboxTo make the preview image look as close as possible to the transmitted image.PictureboxThe image on is set from the scaled image. Previewpicturebox. Image = DEST;
We mustPictureboxThe only other operation that is performed is to ensure thatSizemodeSet propertyZoomSo that the preview image can accurately fill up the preview window. Back to Top Show progress Another useful feature is the progress bar. When you transfer a large number of files, you will be eager to get some prompts about the program Transfer Progress. You can calculate the progress by dividing the number of transferred files by the total number of selected files. This produces a score. We can multiply by 100 to generate a percentage value of the progress bar size. Loadprogressbar. value = (INT) (100 * (float) filecount/(float) nooffiles )); Back to Top Solve the deadlock problem This program can work normally, but there is indeed a problem. Sometimes it takes quite a long time to complete image transmission. During this process, the Error Tracking provided by Visual Studio may determine that the program has stopped. Then, it will cause exceptions that cause program failure. It is not difficult to close the exception. We need to locate the "exception" item (on the "debug" menu item) and then clear it.ContextswitchdeadlockThe "throw" box next to the exception displays the following dialog box: Figure 5: contextswitchdeadlock disabled exception After these operations are completed, the program runs normally even if the transmission volume is large. Back to Top Completed Program The completed program can work normally. I have successfully transferred 127 images to my PlayStation Portable in one way, and I have found that, apart from the images, 127 images only occupy 3.7 MB of space. However, you can also use a large number of enhancements. Back to Top Automatic PlayStation portable detection The PlayStation Portable has a special file arrangement on its storage device. In fact, you must put the images in the \ PSP \ photo directory, otherwise they will not be displayed (take the path in Figure 1 as an example ). The program can check each drive of the system, automatically find the PSP device, and configure it accordingly. Back to Top Drag and Drop Image Transmission In addition to selecting images from the file dialog box, the program can also be dragged to a file in the form. You can then scale and transmit these images. Back to Top Automatic horizontal/Vertical Rotation Smartphone has a portrait display: its height is greater than the width, which is opposite to most images (these images are landscape. This means that the compiled program will not make full use of the screen. This is useful if images can be rotated during transmission so that they can fill the display screen as much as possible. Alternatively, you can provide users with options to allow them to rotate the smartphone image before transmission so that they can display the best results. Rob miles is a lecturer at the computer department at the University of Hull, UK. The Department website is/http://www.net.dcs.hull.ac.uk /. He has been engaged in programming from the very beginning and has always liked this job. He is currently teaching C # and a large number of software engineering courses in this department. In his free time, he will write some essays in his blog (http://www.crazyworldofrobmiles.com) or play games on his Xbox 360. He also likes smartphone and cheese. Go to the original English page
|