Technical details of WebGIS printing implementation -- how to print and preview others -- how cheungmine, the third part of his series, in my previous article, "How WebGIS printing works -- How It Works, display Phase Series II "(see: http://blog.csdn.net/cheungmine/archive/2006/09/18/1238708.aspx), mentions the print principle of WebGIS. In fact, this principle is not only applicable to the printing of WebGIS, but also suitable for printing and previewing. The process of printing a map is actually the process of drawing a map on the print DC. Unlike displaying a map, you need to calculate the scale and convert coordinates.
I. Preparation knowledgeTo understand this process, let me first assume that a basic drawing system requires the following two components: 1) Mapdraw) -- used to draw a picture on a given DC plane. The DC device coordinates must be used for drawing. For example: the DC coordinates must be used in lineto (HDC, VX, Vy). For the screen DC, (VX, Vy) is the pixel, and for the printer DC, It is the dot. 2) coordinate transformation component (viewport)-used to convert the map coordinates to the coordinates of the DC plane and their inverse transformation. In this way, the display and printing process is :.. map Data-> Mapdraw loading-> viewport transformation to DC coordinates-> Mapdraw drawing DC (the implementation of the above two components is beyond the scope of this article. I will only describe how to print .) Set the data range to be printed: rcdata (xmin, ymin, xmax, Ymax ). Given print scale: fscale (for example, = 1/500 ). Suppose we have obtained DC (this DC can be a screen DC, a print DC, or an image DC ). Each DC has attributes: width (width), height (height or long length), xdpi (horizontal resolution), and ydpi (vertical resolution ). The parameters rcdata, width, and height are input to the viewport component to implement the following Transformation :.. map coordinate dp (dx, Dy)-> DC coordinate VP (VX, Vy) DC coordinate VP (VX, Vy)-> map coordinate dp (dx, Dy) the viewport component has dp2vp and vp2dp functions to implement this transformation. We can see that viewport is the core here. It is not difficult to implement viewport. If necessary, I will talk about this transformation class in future articles. Other details, such as margins and alignment, are details. DC can be regarded as a piece of paper, and its coordinate (0, 0) is in the upper left corner of the paper. The ruler (measurement) you use to draw on this paper ), its scale is not M, CM, mm, or inch, but Dot ). You only use this dot to work on this paper. As for how to convert to actual measurement units, such as millimeters (mm), it depends on the attributes of the paper: xdpi and ydpi, they represent the DC resolution in two directions (DPI -- dots per inch, points per inch ). To print a map in proportion, you must note that the size of the paper limits the data range that can be printed on each page. Therefore, you must calculate the data range of the page, when printing each page, you must change the viewport.
In my experience, do not use the coordinate ing API provided by Windows GDI. We only need to use mm_text ing (this is the default one), and the rest will be done by viewport. Repeat it again. Do not use the coordinate ing API provided by Windows GDI for coordinate transformation. It will only confuse you. At least I am not smart enough to leverage these APIs for complex tasks.
Ii. Print and previewImplementing print preview is more complicated than printing. If you have the ability to write something similar to Mircosoft Office document image writer (Modi) for half a year, congratulations, you have achieved print preview. In fact, there is still a problem with Modi itself. For example, the maximum resolution is 300 dpi (too small, isn't it ). Although you can preview the print result by installing a virtual printer, the premise of this mode is to use the 3rd-party software, which is usually paid. The print preview mentioned in this Article does not rely on the payment method, and can print WebGIS. Principles have been discussed in previous articles. The specific steps are as follows :.. map Data-> Mapdraw loading-> viewport transformation to DC coordinates .. -> Mapdraw is drawn to the image DC-> tiff2pdf to generate a PDF file .. we can see that the DC used here is the image DC. You can see how to use it later. Below I will write the pseudo code for printing and previewing, and the whole process will be clear at a glance: //// the following structure defines the attributes of the printed page. // struct print_pdfpage {// page size (unit: pixel). The page is the size tifpage of the remaining part of the paper margin; // The following attributes can be used to construct the coordinate transformation class viewport: rectf rcpagedata; // The page data range, such as: // (20532.123, 1234.678, 34562.112, 2316.870) rect rcpageview; // The DC range corresponding to the page data range, for example: // (0, 0, 2048,204 8 )}; //// the following structure defines the Drawing Structure // struct draw_info {HDC; // page image DC colorref crbkgnd; // background color: = clr_invalid (-1) no background color, // 0x0 ~ 0xffffff indicates that there is a background color. // because PDF is generated by the image, and the image defaults to a black background, you must // fill the background color of the image with viewport VWP; // current coordinate transformation class }; //////////////////////////////////////// //////////////////////////////////////// /The following method implements print preview PDF // use cximage to create a multi-page tiff, converting to PDF // cximage and cximagetif using iis2pdf is a class provided by cximage. See: http://www.xdp.it/// tiff2pdf is a tool provided by LibTIFF, you need to change it to a function //////////////////////////////////// //////////////////////////////////////// /// void printpd F (BSTR bstrpdffilename, // full path name of the PDF file int nmapunit, // map unit float fscale, // print the scale rect rcmargin, // the margin short pdfdpi, // print resolution (DPI), float inpaperwidth (unit: inch), float inpaperlength (unit: inch), and paper height (unit: inch) colorref crbkgnd // background color) {// temporary multipage tif file name ccombstr bstrmultitifs (bstrpdffilename); bstrmultitifs + = ". TIF "; // page array vector <print_pdfpage> arrpdfpages; // calculate the print page array. The calcpdfpages method is used to calculate the data range of each page. // The calcpdfpages prototype is as follows: // calcpdfpages (INT, float, rect, float, // vector <print_pdfpage> &); calcpdfpages (nmapunit, fscale, rcmargin, pdfdpi, inpaperwidth, inpaperlength, arrpdfpages); int npages = (INT) arrpdfpages. size (); // The class cmultitifs used to create multi-page TIF. To implement this class, you only need to know how to use the // cximage and cximagetif classes. For example, the following code creates a 3-page tif file // multipage. TIF: // cximage * pimage [3]; // pimage [0] = & image1; // pimage [1] = & image2; // pimage [2] = & image3; // file * hfile; // hfile = fopen ("multipage. TIF "," W + B "); // cximagetif multiimage; // multiimage. encode (hfile, pimage, 3); // fclose (hfile); // The cmultitifs class must implement cmultitifs mtifs (bstrmultitifs, npages) by itself ); // print each page for (INT ipage = 0; ipage <npages; ipage ++) {// the current page structure print_pdfpage pdfpage = Arrpdfpages [ipage]; // cimage is a C ++ class provided by atl71. I think the only benefit of this class is that it provides getdc. This class has a bug, which is the original // cause of using memdc instead of directly using its DC. I will not create a DC that meets my needs on my own, so please use cimage to represent Laura. Cimage imgdc; // obtain the bitmap DC bool Bres = imgdc only through imgdc. create (16, 16, 32); // create a small bitmap atlassert (Bres); // Note: If the imgdc DC is used directly, when the DPI is changed, only one small part may be printed. I think its DC has problems with Multiple Generation. Therefore, hbitmap is used for conversion. HDC hdcimg = imgdc. getdc (); // obtain the bitmap dc hdc hmemdc =: createcompatibledc (hdcimg); hbitmap hbmp =: createcompatiblebitmap (hdcimg, pdfpage. tifpage. CX, pdfpage. tifpage. cy); atlassert (hbmp); // save DC... int nsaveddc =: savedc (hmemdc);: SelectObject (hmemdc, hbmp); // fill in the drawing structure // draw_info di; Di. HDC = hmemdc; Di. crbkgnd = crbkgnd; // generates coordinate transformation class di. VWP. init (pdfpage. rcpageview, pdfpage. rcpagedata); // draw the page // Drawmap (& di); // recover DC: restoredc (hmemdc, nsaveddc); deletedc (hmemdc); imgdc. releasedc (); imgdc. destroy (); // use cximage to re-open the file cximage * pximg = new cximage (); atlassert (pximg); bool BRC = pximg-> createfromhbitmap (hbitmap) hbmp ); deleteobject (hbmp); // after use, delete atlassert (BRC); // Add image mtifs. addpage (pximg);} // create a multi-page tifbool Bres = mtifs. encode (); atlassert (Bres); // convert TIF to PDF // use the open-source LibTIFF library v 3.8.2. // Download from: http://www.remotesensing.org/libtiff/// You Need To package into your own method: %2pdf %2pdf (bstrmultitifs, bstrpdffilename, pdfdpi, inpaperwidth, inpaperlength );}
Iii. ConclusionHaola, finally said almost. A small question: Do you know how to calculate the size of the page image? Assume that the print resolution is 300 dpi, and the paper size is 8.27x11.69 inch (A4. The page image is: width: 8.27*300 = 2481 pixels high: 11.69*300 = 3507 pixels. In this way, your paper is 2481x3507. All the measurements on this paper are based on this size. Finally, when you convert the page image to a PDF file, do not forget to tell it the DPI you want (300 here! With PDF, you can use Adobe Reader to pull it. It is no better to use Adobe Reader to preview your map than to write one by yourself? It took me a long time to edit my article, but it was still not neat. I couldn't pull it! You cannot add images! Sorry !!