Personal C Sharp                                                         By  famsoft.org
HomeHow To StartExamples-DesktopExamples-WebPC# MethodsReference-DesktopReference-Web


DEMONSTRATIVE EXAMPLES ====================== EXAMPLES ON IMAGING =================== (This section requires version 1.55 or higher) COLOR EDITING: ============== Before learning more about colors, you need to review the "Setting Color and Font" section of the "Personal C Sharp Reference for Desktop applications" and learn the 4 means of setting the color. You should now know that you can select a color by specifying the 4 components which make the color. They represent "red, green, blue and opacity" in sequence and the value of each component can be between 0:255. You load the 4 components into array CLI[] rows and make the assignments (cls="c") before doing an operation which requires selecting color. You need to know two more items: (1) No matter which of the 4 means you have used to set the color, your data is supplied to an internal method which processes the data and outputs the following: a) The Color object referenced by (clp) if your data was for a single color or the two objects (clp) and (clo) if your data was for two colors. b) The array CLI[] loaded with the components of the color(s). This means that CLI[] is always available and always contains the components of the last color set regardless to whether you have used it to spaecify your color or not. (2) If you like to obtain the color object(s) and the components of a specific color code, you can do one of the following: a) Do any operation which requires setting color like displaying text using method tm() or setting paint brush using method gm("sps") b) Call method gm("O") to obtain references to all objects which are used in Graphics. Before this method supplies you with (clp) and (clo) it uses the value of (cls) which you supply or the last value of (cls) available if you don't to obtain them for you. Editing Color Pixel by Pixel: ============================= The simplest way to edit image colors would be by scanning all pixels, reading each pixel color and changing it as necessary. The problem with this method is in being slow. Other color editing methods like using Image Attributes or Color Matrix work much faster. However, the simple method is still the best option in some situations. Method gm() at modes "bcg" and "bcs" are used to get and set a pixel color respecively. The color array CLI[] is used for both modes to define the 4 components of a pixel color. The pixel's horizontal and vertical locations relative to image's center are supplied to the method assigned to (jf,kf) =========================================================================================== Example 1: The image "icon.jpg" which comes with Personal C Sharp package is made of a gray scale text in a pure blue background. We want to scan that image pixel by pixel and change the color of all the pixels which make the background from blue to red. The pixels which make the text should stay unaffected. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { fls="images\\icon.jpg";gm("blf"); // Create a new (bip) and load the file into it. jf=-200;gm("br"); // Draw the image at the left. w=bip.Width/2;h=bip.Height/2; // w,h=half the width and half the height. for (y=-h+1;y< h;y++) { // Scan image vertically for (x=-w+1;x< w;x++) { // and horizontally jf=x;kf=y;gm("bcg"); // Get each pixel's color data if (CLI[0]<100 && CLI[1]<100 && CLI[2]>200) { // If the pixel has high blue and low R,G jf=x;kf=y;CLI=new int[]{255,0,0,255};gm("bcs"); } // Change its color to red. } } jf=200;gm("br"); // Draw the image again at the right. } } =========================================================================================== The most important part of the code is the condition stated to identify background pixels. As we have mentioned before, the background has been originally painted in pure blue. So why can't we use the conditional statement: if (CLI[2]==255) {...} or if (CLI[0]==0 && CLI[1]=0) {...} The problem was caused by "Compression". The image was saved into a "jpeg" file format causing data to be compressed. When the image was read back and returned to its Bitmap form, it did not return to exactly what it was. The background still looks blue, but if you analyze the color components of its pixels, you'll discover that some have a blue component of as low as 220 and some have red and green components as high as 70 each. This is why we have found that we get the best results when we change the conditional statement to: if (CLI[0]<100 && CLI[1]<100 && CLI[2]>200) {...}


BEST SELLERS FROM AMAZON.COM

Books, C Sharp  Books, .NET  Computers  Electronics  Industrial & Scientific Items  MP3 Downloads  DVD
Camera & Photo  Cell Phones & Services  Magazine Subscriptions  Office Products  On Demand Videos




The Image Attributes: ===================== The Image attributes are used for color editing. You can set these attributes using gm("sc") Then, you can modify the present bitmap object (bip)'s color accordingly by calling gm("ba") Method gm("sc") requires that you supply a character code indicating the type of the attribute which you like to set assigned to (oc) before your call. You should also supply the parameter(s) necessary for setting the attribute. Here is a list of the attributes and their identity codes: m : Color mapping. c : Color clearing. g : Gamma Correction. t : Color threshold. o : Output channel. x : Color matrix. w : Wrap mode for Texeture brush. COLOR MAPPING ATTRIBUTE: ------------------------ Used to Replace one or more of the colors found within the image with different one(s). You can set color mapping attributes using more than one trip to the method. In each trip you supply the original color and the color to replace it with. the two colors are supplied to the method using the color components array CLI[] The first 4 rows of that array are for the old color and the other 4 are for the new color. COLOR CLEARING ATTRIBUTE: ------------------------- You supply the method with a lower and upper limits for each color component. If the value of any color component of a pixel was found to lie within the specified range, the pixel will be made transparent. The color limits are also assigned to CLI[]. Rows (0:2) are for the lower limits and rows (4:6) are for the upper limits. GAMMA ATTRIBUTE: ---------------- Gamma is the color contrast. It can be in the range (0.1:5) and is assigned to (jf) COLOR THRESHOLD ATTRIBUTES: --------------------------- The threshold is a value from 0 through 1 that specifies a cutoff point for each color component. For example, suppose the threshold is set to 0.7, and suppose you are rendering a color whose red, green, and blue components are 230, 50, and 220, respectively. The red component (230) is greater than 0.7x255, so the red component will be changed to 255 (full intensity). The green component (50) is less than 0.7x255, so the green component will be changed to 0. The blue component (220) is greater than 0.7x255, so the blue component will be changed to 255. You supply the threshold value assigned to (jf) OUTPUT CHANNEL ATTRIBUTE: ------------------------- When this attribute is set to one CMYK channel, Color is converted to CMYK and the intensity of that channel is calculated for all pixels of the image. When the attribute is applied, the image is redrawn in gray scale using the calculated channel intensity for each pixel. You supply the channel name code assigned to (js) It can be "c", "y", "m" or "k" which means "Cyan", "Yellow", "Magenta" or "Black" respectively. You may specify a Color Profile file name to be used in the calculation of the channel intensity. The path should be assigned to (fls) You may use the file name alone if it was located into the folder: %WINDIR%\system32\spool\color COLOR MATRIX ATTRIBUTE: ----------------------- You can do almost any kind of image color modification using the color matrix. To set this attribute, you supply matrix elements assigned to the 5X5 array of float type CMF[][]. The Color Matrix will be discussed in more details later. WRAP MODE FOR IMAGE TILING: --------------------------- Method gm("spt") which is used to create a texture brush to tile drawn objects with uses this attribute to know how to tile the object with the image assigned to it. To set this attribute you assign to (js) one of the 5 single character codes: c : Clamp. Means Paint one image only on the object. t : Tile the object with as many images as it takes, x : Reverse tiling order horizontally. y : Reverse tiling order vertically. b : Reverse tiling order both horizontally and vertically. =========================================================================================== Example 2: Show the effect of applying different attributes to an image. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { //---------------------- Create new (bip), Draw test pattern on it --------------------- lf=110;of=60;gm("bn");gm("sdb"); // Create 110 X 60 (bip), set as graph. device cls="b0";gm("sps"); // Create solid paint brush of pure blue lf=100;of=50;gm("crf"); // Draw-fill a rectangle gm("sdd"); // Switch graphical out device back to (bio) Bitmap bt=bip; // Save (bip) temporarely jf=-300;kf=150;gm("br"); // Render (bip) as is //--------------------------- Show the effect of Color mapping ------------------------- bip=bt;gm("scn"); // Reset old attributes, prepare for new ones CLI=new int[]{0,0,255,255,255,0,0,255}; // Old color=blue New Color=red oc='m';gm("sc"); // Set Color mapping attribute gm("ba");jf=-100;kf=150;gm("br"); // Apply attributes to (bip) then draw it //------------------- Create new (bip), Load icon.bmp file into it. -------------------- fls="images\\icon.bmp";gm("blf"); // Create a new bitmap object and load file bt=bip; // into it. Save (bip) temporarely jf=100;kf=150;gm("br"); // Render (bip) as is //---------- Show the effect of different attribute setups on resulting image ---------- bip=bt;gm("scn"); // Reset old attributes, prepare for new ones oc='t';jf=0.7f;gm("sc"); // Set color threshold at 0.75 gm("ba");jf=300;kf=150;gm("br"); // Apply attributes to (bip) then draw it bip=bt;gm("scn"); oc='g';jf=0.1f;gm("sc"); // Set Gamma at 0.1 gm("ba");jf=-300;kf=25;gm("br"); bip=bt;gm("scn"); oc='g';jf=1;gm("sc"); // Set Gamma at 1 gm("ba");jf=-100;kf=25;gm("br"); bip=bt;gm("scn"); oc='g';jf=2;gm("sc"); // Set Gamma at 2 gm("ba");jf=100;kf=25;gm("br"); bip=bt;gm("scn"); CLI=new int[]{0,0,0,0,255,0,255,0}; // Color clearing ranges: r=0:255, g=0:0, oc='c';gm("sc"); // b=0:255 Set color clearing attribute gm("ba");jf=300;kf=25;gm("br"); bip=bt;gm("scn"); oc='o';js="c";gm("sc"); // Set attributes for cyan output ch inspection gm("ba");jf=-300;kf=-100;gm("br"); bip=bt;gm("scn"); oc='o';js="m";gm("sc"); // Set attributes for cyan output ch inspection gm("ba");jf=-100;kf=-100;gm("br"); bip=bt;gm("scn"); oc='o';js="y";gm("sc"); // Set attributes for cyan output ch inspection gm("ba");jf=100;kf=-100;gm("br"); bip=bt;gm("scn"); oc='o';js="k";gm("sc"); // Set attributes for cyan output ch inspection gm("ba");jf=300;kf=-100;gm("br"); //---------------------------------- Text Display ------------------------------------- fns="crb16"; // Set font kf=110; os=" Original Color Mapping Original Threshold attr."; gm("ctf"); // Display first line kf=-15; os=" Gamma=0.1 Gamma=1 Gamma=2 Color Clearing "; gm("ctf"); // Display second line kf=-140;os=" Output Channel Output Channel Output Channel Output Channel"; gm("ctf"); // Display third line kf=-160;os=" Cyan Magenta Yellow Black "; gm("ctf"); // Display 4th line } }


============================================================================================ WORKING WITH MATRICES: ====================== Matrices are used in the ".NET" mainly for two purposes: (1) The Affine transform used for object positioning. (2) The Color Matrix used for color editing. We have made your setup of positioning matrix simple and mostly error free by letting you supply the required parameters while we do the entire job for you. Since the order of applying the transformation components can be a cause for errors, we use only one order which is: Scale - Shear - Rotate - Translate We let you base your setup on the PC# method of positioning which defines object locations by the location of their centers relative to form's center. For the color matrix, things are different. Using the color matrix to edit image colors is the job of a professional who likes to handle the details of his job by himself. So we'll let you calculate by yourself the matrix elements necessary for the color transformation job. Let us have a very brief study of matrices to see how this job can be done. Although you have no need to learn about the object positioning matrix, We are going to start with it in this study since it is simpler. PC#'s transformation order and positioning will not be considered in this study. The object postioning matrix: ----------------------------- If we like to move point (x,y) to a new position (x1,y1) and try to find a general formula to be used to calculate the new coordinates based on all the variables involved while assuming linear relationships, the formula would be: x1 = ax + by + c and y1 = dx + ey + f where a,b,c,d,e and f are constants. The constant (a) which represents the new x-position as a function of the old (x-position) is called the x-scaling factor. Similarly, (e) is the y-scaling factor. The constant (b) which represents the new x-position as a function of the old (y-position) is called the x-shearing factor. Similarly, (d) is the y-shearing factor. The constants (c) and (f) are called the x-translation factor and the y-translation factor respectively. We can now rewrite the formulae above as follows: x1 = xScale.x + xShear.y + xTrans and y1 = yShear.x + yScale.y + yTrans Mathematicians have found a more convenient way to represent these formulae and many other similar ones using what they called "matrix". They also set rules for how to apply arithmatic operations like addition and multiplication to matrices. In our case, the old and new point positions can be expressed as the two matrices: [x y 1] and [x1 y1 1] respectively and the 2 formulae above can be expressed as: [xScale yShear 0] [x1 y1 1] = [x y 1] . [xShear yScale 0] [xTrans yTrans 1] Applying the rules set for multiplication of matrices, the formula above leads to: [x1 y1 1] = [x*xScale + y*xShear +1*xTrans x*yShear + y*yScale + 1*yTrans 1] and this is exactly what our original two formulae say. According to matrices math, we can make a seperate matrix for each of the three operations (scaling, Shearing, and translation) as follows: Scaling: [xScale 0 0] Shearing: [ 1 yShear 0] Translating: [ 1 0 0] [ 0 yScale 0] [xShear 1 0] [ 0 1 0] [ 0 0 1] [ 0 0 1] [xTrans yTrans 1] Then the matrices can be multiplied together in order to come up with the a matrix which represents the combined operations. The order into which the multiplication takes place is important. This is because a change in the order of applying the three operations to relocate point (x,y) can change the result. In order to simplify forming the 3 matrices above, start with the identity matrix which is: [ 1 0 0 ] [ 0 1 0 ] [ 0 0 1 ] The identity matrix does no transformation since it scales the object 1:1, adds no shearing components and moves the object in both directions by zero pixels. Rotation creates its own scale and shear components for both x and y. Rotation by the angle (a) can be represented by the matrix: [ cos a sin a 0] [-sin a cos a 0] [ 0 0 1] Now you have 4 matrices representing scaling, shearing, rotatation and translation. To obtain the overall positioning matrix you multiply the four together in the order at which you like the transformation to take place. Multiplication of matrices: --------------------------- A matrix element is defined by its (row,column) Order numbers of rows and columns start by zeros. A matrix is defined by its (Number of rows, Number of columns) like A(1,3) You can multiply two matrices together if the number of columns of the first one matchs the number of rows of the second one. so you can multiply A(2,4) X B(4,3) and the result will be C(2,3) Element c(x,y) of the resulting matrix (C) can be obtained by multiplying each element at the (xth) row of (A) by the element at the (y)th column of (B) which matches it in order then adding all resulting values together. The Color Matrix: ----------------- The color matrix is similar except that it is a 5X5 matrix in the form: [rScale grShear brShear arShear 0] [rgShear gScale bgShear agShear 0] [rbShear gbShear bScale abShear 0] [raShear gaShear baShear aScale 0] [rTrans gTrans bTrans aTrans 1] To transform a color with the red, green, blue and alpha components (r,g,b,a), multiply the matrix [r g b a 1] by the color matrix above. You should have noticed that there are 3 shear factors for each color component. The 3 factors represent the component's relation with each of the three other components. Similarly There are also 3 rotation factors for each component. If we eliminate the alpha component, the total of all rotation factors becomes 6. Here are the matrices necessary to perform all 6 types of rotations assuming that the rotation angle is (a): ---------------------------------------------------------------------------------------------- [ cos(a) sin(a) 0 0 0 ] [ 1 0 0 0 0 ] [ cos(a) 0 -sin(a) 0 0 ] [-sin(a) cos(a) 0 0 0 ] [ 0 cos(a) sin(a) 0 0 ] [ 0 1 0 0 0 ] [ 0 0 1 0 0 ] [ 0 -sin(a) cos(a) 0 0 ] [ sin(a) 0 cos(a) 0 0 ] [ 0 0 0 1 0 ] [ 0 0 0 1 0 ] [ 0 0 0 1 0 ] [ 0 0 0 0 1 ] [ 0 0 0 0 1 ] [ 0 0 0 0 1 ] Rotation of red toward green Rotation of green toward blue Rotation of blue toward red ---------------------------------------------------------------------------------------------- [cos(a) -sin(a) 0 0 0 ] [ 1 0 0 0 0 ] [ cos(a) 0 sin(a) 0 0 ] [sin(a) cos(a) 0 0 0 ] [ 0 cos(a) -sin(a) 0 0 ] [ 0 1 0 0 0 ] [ 0 0 1 0 0 ] [ 0 sin(a) cos(a) 0 0 ] [-sin(a) 0 cos(a) 0 0 ] [ 0 0 0 1 0 ] [ 0 0 0 1 0 ] [ 0 0 0 1 0 ] [ 0 0 0 0 1 ] [ 0 0 0 0 1 ] [ 0 0 0 0 1 ] Rotation of green toward red Rotation of blue toward green Rotation of red toward blue ---------------------------------------------------------------------------------------------- As mentioned before, always start with the identity matrix when you try to create the necessary matrix for an operation. The identity matrix in this case is: [ 1 0 0 0 0 ] [ 0 1 0 0 0 ] [ 0 0 1 0 0 ] [ 0 0 0 1 0 ] [ 0 0 0 0 1 ] How to supply the matrix data to method gm("sc"): ------------------------------------------------- (1) Decide upon the operation(s) which you like to apply to each color and form the necessary matrix for each operation (on paper) (2) Multiply all matrices together at the order which you see necessary to come up with the final color transformation matrix. (3) Assign the final matrix elements to the elements of array CMF[][]. Array CMF[][] is a 5X5 array of float type which has been predefined for you. As an example, If the data at the matrix element located at row number (0) and column number (2) was 5, make the assignment: CMF[0][2]=5; In order to make your job easy, the array comes to you with the identity matrix already assigned to it. So you overwrite the elements which you like to change only. The rest should be kept as is. For example, if all you want to do was to scale the red component of the color by a factor of 2, you'll only need to make the assignment: CMF[0][0]=2; and the color matrix array will be ready to go. REMARK: ======= A translation of (0.5) does not mean adding (0.5) to the color component. It actually means adding (0.5 * 255 = 127.5) The GDI+ uses different system to represent color components within the color matrix. =========================================================================================== Example 3: Create a bitmap and draw a color pattern on it, then show how applying different setups to the color matrix and modifying the image accordingly can change the look of the image. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { float sine,cosine; // Define 2 var's for sin & cos an angle //---------------------- Create new (bip), Draw test pattern on it --------------------- lf=125;of=60;gm("bn");gm("sdb"); // Create 125 X 60 (bip), set as graph. device cls="r5";gm("sps"); // Create solid paint brush of light red jf=-50;lf=25;of=50;gm("crf"); // Draw-fill a rectangle cls="G5";gm("sps"); // Change color to dark green jf=-25;lf=25;of=50;gm("crf"); // Draw-fill another rect beside first one cls="b0";gm("sps"); // Change color to pure blue lf=25;of=50;gm("crf"); // Draw-fill another rect cls="s9";gm("sps"); // Change color to white jf=25;lf=25;of=50;gm("crf"); // Draw-fill another rect cls="S9";gm("sps"); // Change color to black jf=50;lf=25;of=50;gm("crf"); // Draw-fill another rect gm("sdd"); // Switch graphical out device back to (bio) Bitmap bt=bip; // Save (bip) temporarely jf=-300;kf=125;gm("br"); // Render (bip) as is //---------- Show the effect of different ColorMatrix setups on resulting image --------- bip=bt;gm("scn"); // Reset old attributes, prepare for new ones oc='x';CMF[0][0]=0.5f;gm("sc"); // Set ColorMatrix attrib at rScale=0.5 gm("ba");jf=-100;kf=125;gm("br"); // Apply attributes to (bip) then draw it bip=bt;gm("scn"); // Reset old attributes, prepare for new ones oc='x';CMF[1][1]=CMF[2][2]=0.5f;gm("sc"); // gScale=bScale=0.5 gm("ba");jf=100;kf=125;gm("br"); // Apply attributes to (bip) then draw it bip=bt;gm("scn"); // Reset old attributes, prepare for new ones oc='x';CMF[4][0]=0.75f;gm("sc"); // rTrans=0.75 gm("ba");jf=300;kf=125;gm("br"); // Apply attributes to (bip) then draw it bip=bt;gm("scn"); CMF[4][0]=CMF[4][1]=CMF[4][2]=0.5f; // Transform red, green & blue by 0.5 pixels gm("sc"); oc='x';gm("ba");jf=-300;kf=0;gm("br"); bip=bt;gm("scn"); oc='x';CMF[1][1]=1.25f;CMF[4][1]=0.5f; // gScale=1.25, gTrans=0.5 gm("sc"); gm("ba");jf=-100;kf=0;gm("br"); bip=bt;gm("scn"); oc='x';CMF[0][1]=0.25f;gm("sc"); // grShear=0.25 gm("ba");jf=100;kf=0;gm("br"); bip=bt;gm("scn"); oc='x';CMF[2][0]=CMF[2][1]=0.5f;gm("sc"); // rbShear=gbShear=0.5 gm("ba");jf=300;kf=0;gm("br"); bip=bt;gm("scn"); oc='x';CMF[1][0]=0.25f;gm("sc"); // rgShear=0.25 gm("ba");jf=-300;kf=-125;gm("br"); bip=bt;gm("scn"); od=90;js="sin";um("mt");sine=(float)od; // Get sin(90), assign it to (sine) od=90;js="cos";um("mt");cosine=(float)od; // Get cosine(90), assign it to (cosine) CMF[0][0]=CMF[1][1]=cosine; // Make the setups for color rotation CMF[0][1]=-sine;CMF[1][0]=sine; // of red component toward green one oc='x';gm("sc"); gm("ba");jf=-100;kf=-125;gm("br"); bip=bt;gm("scn"); CMF[1][1]=CMF[2][2]=cosine; // Make the setups for color rotation CMF[2][1]=-sine;CMF[1][2]=sine; // of green component toward blue one oc='x';gm("sc"); gm("ba");jf=100;kf=-125;gm("br"); bip=bt;gm("scn"); CMF[0][0]=CMF[2][2]=cosine; // Make the setups for color rotation CMF[0][2]=-sine;CMF[2][0]=sine; // of blue component toward red one oc='x';gm("sc"); gm("ba");jf=300;kf=-125;gm("br"); //---------------------------------- Text Display ------------------------------------- fns="crb16"; // Set font cls="r0";gm("sps"); // Prepare red pen kf=175;os="USING THE COLOR MATRIX FOR COLOR EDITING";gm("ctf"); // Display title cls="b0";gm("sps"); // Prepare blue pen kf=85; os=" Original rScale=0.5 gScale=bScale=0.5 rTrans=0.75 "; gm("ctf"); kf=-40; os="r,g,b Trans=0.5 gScale=1.25,gTrans=0.5 grShear=0.25 rbShear=gbShear=0.5"; gm("ctf"); kf=-165;os="rgShear=0.25 g-r Rotation g-b Rotation b-r Rotation "; gm("ctf"); } // Display all other text } =========================================================================================== Can you make sense of the results you get from the Color Matrix? ---------------------------------------------------------------- The Color Matrix is a very powerful tool. It must be very useful to the experts in this field. However, to a normal person, some of the logics involved are hard to make sense of. Here is an example: Let us assume that your image was nothing but a white rectangle and you decided to increase its red component by 50%. So you made the assignment (CMF[0][0]=1.5f) Guess what the white color will turn into. May be your answer is "no change" since the red component in the white color was already at its maximum value of (255) before the transformation took place. This is not what you get. The reason is that whenever the ".NET Graphics Device Interface" (GDI+) finds that a color component was going to exceed (255), it subtracts (255) from the result leaving only the remainder. In our case the remainder is (255*1.5 - 255 = 127.5) So the red component actually went down in value causing the resulting color to look like "Cyan". What makes things even harder to make sense of, is that the formula mentioned above is used by GDI+ whenever the overflow is caused by scaling or shearing. If it was caused by translation the value of the red component could have stayed the same at 255 and the rectangle could have remained white. SUGGESTION: =========== We are not sure why the GDI+ uses this logic. However we think that the logic which can make an ordinary person able to make sense of the results obtained by using the color matrix would require the following procedures: (1) The 3 color components should be computed normally to start with, regardless to overflow or underflow and regardless to the operation(s) performed. (2) If any component was found to be over 255, its value should be reduced to 255 and the other two color components should be reduced by the amount of the overflow. (3) If any component was found to be negative its value should be increased to zero and the other two color components should increase in value by the absolute value of the negative amount. If these rules have been applied, the resulting color components of the white rectangle which has been used to illustrate this problem could have become: Red: 255 Green: 127.5 Blue: 127.5 and the color of the white rectangle could have become light red.


============================================================================================ IMAGE FILES =========== The Bitmap Object: ================== The Bitmap is an array of bits which specifies the color of each pixel in a rectangular array of pixels. The number of bits representing each color can be any number between 1 and 32. For the bitmaps we use, the number is 32, eight for each of the color components red, green,blue and alpha. This means that the decimal value of each component can be 0:255. The color palette: ------------------ Some bitmaps, especially the ones which use small amounts of bits to represent colors contain tables called color pallettes. The tables contain lists of colors and indices to them. The indecies are used in the color tables to represent the colors instead of the colors themselves. The image file formats: ======================= BMP format: ----------- The common type uses 24 bits, however their number of bits which represent colors can be 1:64. This value is specified in the file header. Bitmap files are not compressed which is good for quality but not for size. GIF (Graphics Interchange format): ---------------------------------- This type is good for animation since it can carry more than one frame and allows one color to be designated as transparent. It is more suitable for drawings than for photographs. It is limited to 8 bits/color. It is compressed but no information is lost in the process. It's not a public property like other formats are. One company claims copyright on this file format. PNG (Portable Network Graphics): -------------------------------- Similar to "GIF" except that it can represent colors with 8:48 bits and can store alpha values. JPEG (Joint Photographic Experts Group): ---------------------------------------- This type is more suitable for photographs than for drawings. It can be made with different quality factors. The higher the quality factor the lower the compression used. EXIF (Exchangeable Image File): ------------------------------- Similar to "jpeg" except that it contains useful information for digital camera users like date picture was taken, shutter speed and camera make & model. TIFF (Tag Image File Format): ----------------------------- This is a flexible format in which many encoding parameters are settable. It allows storing many kinds of information. It allows variety of compression algrithms and color depth settings It can also store more than one image per file. MetaFiles: ---------- This is a unique image file format. Instead of storing color information for each pixel of the image, metafiles store instructions and settings for how to draw the image. We are going to be discussing this fascinating image format in details soon. Saving an image file: ===================== If you check "PC# methods", you'll see that method gm() at modes starting with "bs" is used for saving the present bitmap object (bip) into file. If you like to use default settings, use the 3-character modes. For example, use mode "bsj" to save (bip) into a file using "jpeg" format with default settings. If you like to set your own encoding parameters, use mode "bs". At this mode, you can specify the color depth, which means the number of bits used to represent a color, the compression scheme and the color quality. Additionally, you can set the image file as a multi-frame file into which you can store more than one bitmap object. There are limitations. According to Microsoft documentation, the current GDI+ version only allows few of the setups planned. Additionally, each file format allows only few of its parameters to be settable. So, be prepared to get the error message "Parameter is not valid" sometimes when you try different setups. Multi-frame files: ------------------ We'll see in the next example how to set a "TIFF" file to be a multi-frame image file and store three images into it. Frames are planned to be of three types: (1) Time-based for annimation. (2) Resolution-based which stors multi-resolution versions of one image. (3) Page-based which stores any number of different images. Unfortunately, the only type which is currently ready for use is the page-based. Reading a multi-frame file: --------------------------- There are two modes in method gm() which perform operations that require reading image flles. Mode "cid" which draws an image on the graphical output device and mode "blf" which creates a new bitmap and loads an image file into it. Both modes can handle multi-frame files and can operate on a particular frame within a file if you supply its index assigned to (i). Mode "blf" additionally checks the file you supply and counts the number of frames it contains. It returns the count to you assigned to (os) The reason it assigns the count to (os) although it's an integer is that method gm() resets (o) and most other o-based numerics at its end. Next example will show how to read and display the images stored into a multi-frame file. Parameters used by gm("bs"): ---------------------------- i : Color depth. Number of bits which represnt a color. k : Quality factor. A number in the range 1:100 which specifies quality. The higher the quality the less the level of compression used. ks : Compression scheme. This can be: "none", "rle", "lzw", "ccitt3" or "ccitt4". ib : Multi-frame flag. ib=true means set file for multi-frame use and store all the bitmap images assigned to the bitmap array BIP[] into it. ib=false means set the file for single frame use and store (bip) into it. bip: Image to be stored into a single frame file. BIP: Array of images to be stored into a multi-frame file. =========================================================================================== Example 4:Create 3 bitmap objects using the 3 files icon.bmp, flower.jpg and pix.jpg and save them all into a single multi-frame TIFF file. Set the color depth for all at 24 bits and use LZW compression. After the file is saved, read it back, get and display its frame count and display the 3 images it contains at different locations. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { //------------------------------ Saving (encoding) file ------------------------------- fls="images\\icon.bmp";gm("blf");BIP[0]=bip; // Load 1st file and assign it to BIP[0] fls="images\\flower.jpg";gm("blf");BIP[1]=bip; // Load 2nd file and assign it to BIP[1] fls="images\\pix.jpg";gm("blf");BIP[2]=bip; // Load 3rd file and assign it to BIP[2] // Parameters: Color depth=24 bits, LZW compression, multi-frame tiff file format i=24;ks="lzw";ib=true;fls="test.tiff";gm("bs");// Save file using encoder parameters //------------------------------ Reading (decoding) file ------------------------------ fls="test.tiff";i=0;gm("blf"); // Load frame 0 of file. Get frame count. cls="b0";gm("sps");fns="trb20"; // prepare color and font for text display os="File "+fls+" contains "+os+" frames."; // Prepare frame count message kf=-125;gm("ctf"); // Display message jf=-250;gm("br"); // Display image at frame 0. fls="test.tiff";i=1;gm("blf");jf=0;gm("br"); // Get & display image at frame 1. fls="test.tiff";i=2;gm("blf");jf=250;gm("br"); // Get & display image at frame 2. } }


============================================================================================ METAFILES ========= Meta files are unique image files. Most image files contain color information for the pixels which make an image while metafiles contain instructions and settings for how to draw the image. Metafiles have the following advantages over other image file types: (1) Smaller size. While the size of a regular image file depends on the size of the image it represents, the size of a metafile depends on how sophisticated the drawing instructions are. Normally, a metafile is considerably smaller in size than other image file types with comparable quality. (2) Maximum quality. When a metafile runs, it reproduces the image from scratch on the machine which runs it. No drop in quality can occure due to data compression or any other reason. (3) Flexiblity. They are made of small size records. You can run some and skip the rest. USING METAFILES: ================ As you expect, we have developed the means to make you able to handle metafiles in an extremely simple and pleasant manner. You can perform 3 operations on a metafile: (1) Display the file as one piece. This can be done by simply assigning the file name to (fls) and calling gm("cid") This mode is general to all image file types. (2) Record a metafile. You start by calling gm("mow") to open the file for "writing". Once this is done, you can make the metafile your "Graphical output device" by calling gm("sdm") Anything you draw thereafter will be automatically recorded into the file. At the end, you close the file by calling gm("mc") (3) Read a metafile record by record. You start by calling gm("mor") to open the file for "reading". Once this is done, method update() will be receiving all record data one by one. Within method update(), you can alter the data if you like, but you don't have to do anything other than calling gm("mr") to read and display the graphical data as is. At the end you close the file by calling gm("mc") Using blocks within a metafile: ------------------------------- To allow you more control and power, we made it possible for you to divide your file into blocks, just like you do with your code. When you read the file you can fast forward it to a specific block before you start reading the data. PC# saves block numbers into the file in the form of comment records While writing to the file, at any moment you can call gm("mwb") to write the block number number which you supply assigned to (bli) into the metafile. While reading, you always have the option of either calling gm("mr"), to read and display the record as explained above, or calling gm(mrb) with a block number assigned to (bli) to perform a fast forward operation. The file will be searched through until the comment record which contains the block number is reached. Flexibility while writing into the metafile: -------------------------------------------- While writing into the metafile, you don't have to keep it as your graphical output device all the time. As you know drawing sometimes requires other devices to be made the graphical output device temporarely like we do sometimes with (bip) Therefore, we have made it possible to switch devices and return back to the metafile without losing file integrity. You need to know here that graphical data is written into the metafile only when the file is the graphical output device. During the time another device is the output device, the file stays on halt. ========================================================================================== Example 4: This example will demonstrate how to draw a red and a blue circles directly into a metafile. At the middle of the operation, the graphical output device will be switched to the default bitmap and a green circle will be drawn to it before it will be switched back to the metafile. At the end the file will be displayed in full using method gm("cid") on the default bitmap. Since the green circle was drawn on the default bitmap, the three circles will show together. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { //--------------------------------- Writing to file ---------------------------------- fls="test.emf";gm("mow"); // Open metafile for writing // Draw red circle into file gm("sdm"); // Set it as the graphical output device bli=1;gm("mwb"); // Write "block=1" label cls="r0";gm("sps"); // Create solid red pen jf=-150;lf=of=150;gm("cef"); // Draw-fill red circle at (-150,0) // Draw green circle on the screen gm("sdd"); // Switch graphical output device to (bio) cls="g0";gm("sps"); // Create solid green pen lf=of=150;gm("cef"); // Draw-fill green circle at center // Draw blue circle into file gm("sdm"); // Return graphical output device back to metafile bli=2;gm("mwb"); // Write "block=2" label cls="b0";i=5;gm("sps"); // Create solid blue pen jf=150;lf=of=150;gm("cef"); // Draw-fill blue circle at (150,0) gm("sdd"); // Switch graphical output device to (bio) gm("mc"); // Close metafile //----------------------------------- Display file ------------------------------------ fls="test.emf";gm("cid"); } } ===========================================================================================


============================================================================================ Reading the metafile data back: ------------------------------- Immediately after opening the file for reading, method update will be receiving record data in order starting with first record in the file. As you know, each call to method update must be accompanied with an assignment to (cs) which identifies the source of the event. The metafile call is identified with the assignment (cs="mf") Additionally method update() receives the following with each call: (1) Metafile block number (mbi): As you have seen in the previous example, each block of code in the metafile can be identified with a block number. The block number label is placed as a comment record at the top of the code block. Before method update() is called with a new record data, PC# software checks to see if it was a new block label. If it was found to be, it reads the block number and assigns it to (mbi) Additionally it sets (ob) to let you know that this is a block label record. If the next record was a data record, the flag (ob) is reset and the assignment to (mbi) stays the same since the data record belongs to the same block number. The new assignments are repeated with all following records until a new block label record is encountered. (2) Block label record identifier (ob): As described in (1), (ob=true) means that the current record is a block identifier record. (3) End of file record identifier (jb): It is essential to check the assignment to (jb) after each call is received by method update() Whenever (jb=true), gm("mc") must be called in order to close the operation. (4) Type of present record (mrp) (5) Metafile Flags (of) (6) Data Size (od) (7) Data (OY) You'll need to use items (4:7) if you like to do more than just displaying file's data without modification. We are not going to use them in the next example. How to design your metafile reading program? -------------------------------------------- As you know, method run() starts immediately after methods init() and setup() are executed. Therefore, opening the file should be in run(). You should prepare a block in method update() which handles the metafile data. The same block will be called again and again with the data for each record, so you must make sure to condition your statements so that each statement is executed only when the right record comes. After receiving each record you should do one of the following: (1) Call method gm("mr") to read and display the data. Make sure to keep the received data (mrp,of,od and OY) unchanged since they are used by this method. (2) Call method gm("mrb") to fast forward through the file until a new block is reached. You supply the new block number assigned to (bli) (3) Return without calling either method. When you receive the label record of a new block, you have a chance to do some operations which are irrelated to the metafile data, like interfacing with the user or displaying additional messages or drawings which are necessary for the job. The record itself contains no data which can be displayed. =========================================================================================== Example 7: In this example, we are going to read back file "test.emf" and display its contents. Immediately before each of the two circles is displayed, the display process will be interrupted with a message to inform the user of the coming display. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void update() { if (cs.Equals("mf")) { // If this was a metafile record read call: if (mbi<1) { // If file pointer was before block 1: bli=1;gm("mrb");return; // Fast Forward to block 1. } if (mbi==1) { // If pointer is now at or after block 1's label: if (ob) { // If "at the label" display message then os="Click to get the red circle";cm("d"); return; // return since label record has nothing to display } gm("mr"); // If at data records following block 1's label, } // display it. if (mbi==2) { // If pointer is now at or after block 2's label: if (ob) { // proceed similarly. os="Click to get the blue circle";cm("d"); return; } gm("mr"); } if (jb) gm("mc"); // Close metafile. } } public override void run() { jf=0;kf=0;fls="test.emf";gm("mor"); // Open metafile for read , set display center point } // at form's center. }


BEST SELLERS FROM AMAZON.COM

Books, C Sharp  Books, .NET  Computers  Electronics  Industrial & Scientific Items  MP3 Downloads  DVD
Camera & Photo  Cell Phones & Services  Magazine Subscriptions  Office Products  On Demand Videos




============================================================================================ IS THERE ANYTHING WHICH WE CANNOT DO TO AN IMAGE? ================================================= Let us list what we are able to do: (1) We can draw the image at any location using gm("br") (2) We can set the image as the graphical output device using gm("sdb") and draw anything on its surface, then change graphical output device and draw the modified image on the new device. (3) We can set Affine transform to rotate the image by any angle using gm("stu") then draw the image while applying the transform using gm("brt") (4) We can apply any shearing to the image using the same methods as in (3) (5) We can scale the image by any amount using several means, one of them is the same as in (3) (6) We can crop the image and we are not limited to rectangular cropping. The cropping can take any shape like a circle, ellipse or hexagon. We are going to see example on that next. (7) We can crop and reduce the file size of the image. This has been done in example 11 of the "Drawing" chapter and will be demonstrated in a new example. (8) We can save the image into file of any format. This has been demonstrated in the same example. (9) We can edit the color of all pixels of the image using several methods. Color mapping and color matrix are some of them. 10) We can save more than one image in a single file and can select the color depth and the compression scheme to be used. 11) We can create an image metafile which stores the image in the form of drawing instructions. 12) We can use the image to tile any shape object with tiling pattern which is settable by image attributes. We believe that everything possible to do to an image has been covered. However, cropping, shearing and rotaing an image are good to be demonstrated in the next example. =========================================================================================== Example 7: Show how to give an image a hexagonal borders. Also show how to apply shearing and rotation to an image. =========================================================================================== public class a : pcs { public override void init() { base.init(); } public override void run() { fls="images\\flower.jpg";gm("blf"); // Create new (bip) and load an image file into it. lf=6;of=200;gm("c="); // Create a Hexagon gm("gc"); // Set the hexagon as the clip area. gm("br"); // Draw the image. gm("gcn"); // Cancel previous setup of Clip area ad=10;lf=-250;gm("stu"); // Create Affine xform to rotate image 10 degrees and gm("brt"); // move it to left. Draw image applying the transform id=0.3;lf=250;gm("stu");gm("brt"); // Draw image after applying horiz shear of 0.3 } }


=============================================================================================== Cropping with file size reduction: ---------------------------------- If you like to eliminate the empty area around an image completely in order to reduce its file size, proceed as follows: (1) Create a new (bip) and Load the image file into it at full scale. (2) Resize Form to the wanted reduced size of the image. (bio) will automatically be recreated in order to make it match the new size of the Form. (3) Draw (bip) on (bio) at coordinates which allow the wanted portion of the image to appear. (4) Make (bip) another reference to the default Bitmap object (bio) (5) Save (bip) =============================================================================================== Example 8: Eliminate empty margins around the image in "images\\flower.jpg" and save the reduced image into file "ReducedImage.jpg". =============================================================================================== public class a:pcs { public override void run() { fls="images\\flower.jpg"; // Create a new (bip) and lf=of=0;gm("blf"); // load file into it at scale 1:1 j=140;k=170;cm("fs"); // Resize form (and bio) to wanted image size. kf=10;gm("br"); // Draw image at coord's which allow wanted section bip=bio; // to appear. Assign (bio) object to (bip) fls="ReducedImage.jpg";gm("bsj"); // Save (bip) } } ----------------------------------------------------------------------------------------------- Compile and run this program and compare the new file size to the original one. You should find that the file size which has been originally 11,142 bytes has been reduced to 9,411 bytes. ===============================================================================================