Wednesday, November 4, 2009

Chapter 3. HTML Optimization




[ Team LiB ]









Chapter 3. HTML Optimization



HTML is still the lingua franca for publishing hypertext documents on the web. With simple markup tags like <h1> and </h1> used to denote structure, HTML has become the universal language of the web. As designers and browser manufacturers morphed HTML into the web equivalent of PageMaker, however, HTML code became too verbose with presentational tags, scripts, and objects intermixed with structural markup. This chapter and the ones that follow show you how to optimize and simplify your code for maximum speed, while still maintaining the functionality and visual appeal of your site.


Ask any group of users today what makes the web so slow, and you'll hear about large video, Flash, and image files. You might hear about overused and unoptimized Java and JavaScript. What is seldom mentioned is bloated HTML. Yet HTML size is the one web page component that users cannot control. They can turn off JavaScript, images, plug-ins, and Java, but they can't turn off HTML bloat�only designers can.


Because it has looser rules, HTML offers more opportunities for optimization than its newer cousin, XHTML. In HTML, you can omit some end tags and abbreviate attributes and still have a valid document. In XHTML, every tag must be closed, every attribute fully qualified and quoted. Because HTML offers more opportunities for savings and it isn't going away anytime soon, it is the focus of this chapter. Chapter 5, "Extreme XHTML," focuses on optimizing XHTML, which can use a subset of the techniques discussed here.









    [ Team LiB ]



    12.4 Bitmap Color




    < BACK  NEXT >

    [oR]

    12.4
    BITMAP COLOR TRANSFORMATION


    There are numerous algorithms that need to transform color for each pixel in the bitmap in a certain way. A color transformation is applied to each pixel independently and without a global context. Sample usage for this group of algorithms includes converting color bitmaps to grayscale, gamma correction, color space conversion, adjusting bitmap hue, lightness, or saturation, etc.



    Such bitmap color transformation algorithms have the same pattern. If the bitmap has a color table, each entry in the color table needs to be transformed. Otherwise, we have to scan through each pixel in the pixel array and apply a transformation to each of them. An easy way to implement them would be to use a generic algorithm and a function pointer parameter. Each color transformation is a simple static function. To transform a bitmap with a given color transformation, just call the generic algorithm with the specific color transformation routine a parameter. A similar way is to define an abstract color transformation class, which has a virtual member function that does the color transformation.



    Performance is normally considered critical for bitmap-handling algorithms, so calling a function or a virtual function for every pixel in a huge bitmap is normally unacceptable. We certainly do not want to repeat the same code over and over again, nor would we like to use macro-based programming. So the only alternative is a template function.



    We would like to define these algorithms on the KDIB class. But the trouble with a template function is that our available C++ compiler does not support a template member function. So we have to use a static template function that accepts a pointer to a KDIB instance. To make things worse, our C++ compiler does not support a friend template function, which forces us to change some private members to be public members.



    Listing 12-4 shows a template-based DIB color transformation algorithm.





    Listing 12-4 Template for Bitmap Color Transformation Algorithms


    template <class Dummy>
    bool ColorTransform(KDIB * dib, Dummy map)
    {
    // OS/2 DIB color table: 1,4,8-bpp, include RLE compression
    if ( dib->m_pRGBTRIPLE )
    {
    for (int i=0; i<dib->m_nClrUsed; i++)
    map(dib->m_pRGBTRIPLE[i].rgbtRed,
    dib->m_pRGBTRIPLE[i].rgbtGreen,
    dib->m_pRGBTRIPLE[i].rgbtBlue);

    return true;
    }

    // Windows DIB color table: 1,2,4,8-bpp, include RLE compression
    if ( dib->m_pRGBQUAD )
    {
    for (int i=0; i<dib->m_nClrUsed; i++)
    map(dib->m_pRGBQUAD[i].rgbRed,
    dib->m_pRGBQUAD[i].rgbGreen,
    dib->m_pRGBQUAD[i].rgbBlue);

    return true;
    }

    for (int y=0; y<dib->m_nHeight; y++)
    {
    int width = dib->m_nWidth;
    unsigned char * pBuffer = (unsigned char *) dib->m_pBits +
    dib->m_nBPS * y;

    switch ( dib->m_nImageFormat )
    {
    case DIB_16RGB555: // 15-bit RGB color image, 5-5-5
    for (; width>0; width�)
    {
    BYTE red = ( (* (WORD *) pBuffer) & 0x7C00 ) >> 7;
    BYTE green = ( (* (WORD *) pBuffer) & 0x03E0 ) >> 2;
    BYTE blue = ( (* (WORD *) pBuffer) & 0x001F ) << 3;

    map( red, green, blue );
    * ( WORD *) pBuffer = ( ( red >> 3 ) << 10 ) |
    ( ( green >> 3 ) << 5 ) |
    ( blue >> 3 );

    pBuffer += 2;
    }
    break;

    case DIB_16RGB565: // 16-bit RGB color image, 5-6-5
    for (; width>0; width�)
    {
    BYTE red = ( (* (WORD *) pBuffer) & 0xF800 ) >> 8;
    BYTE green = ( (* (WORD *) pBuffer) & 0x07E0 ) >> 3;
    BYTE blue = ( (* (WORD *) pBuffer) & 0x001F ) << 3;

    map( red, green, blue );

    * ( WORD *) pBuffer = ( ( red >> 3 ) << 11 ) |
    ( ( green >> 2 ) << 5 ) |
    ( blue >> 3 );

    pBuffer += 2;
    }
    break;

    case DIB_24RGB888: // 24-bpp RGB
    for (; width>0; width�)
    {
    map( pBuffer[2], pBuffer[1], pBuffer[0] );
    pBuffer += 3;
    }
    break;

    case DIB_32RGBA8888: // 32-bpp RGBA
    case DIB_32RGB888: // 32-bpp RGB
    for (; width>0; width�)
    {
    map( pBuffer[2], pBuffer[1], pBuffer[0] );
    pBuffer += 4;
    }
    break;
    default:
    return false;
    }
    }

    return true;
    }

    The ColorTransform function accepts two parameters: a pointer to a KDIB instance and a function pointer. It's strange to pass a function pointer a template function without specifying the function prototype. But apparently, this method is supported and used by STL. The first part of the function handles the color table in the OS/2 BMP file format; each of the RGBTRIPLE structures is handled by calling the color transformation function through the map parameters. The color transformation routine accepts three reference parameters for the red, green, and blue channels, and returns the transformed color using the same variable. The code handling Windows color table is very similar, except now the RGBQUAD structure needs to be mapped. This part of the code handles all palette-based DIB formats, including RLE compressed and uncompressed formats.



    The remaining code handles 16-bit high color bitmaps, 24-bit true color bitmaps, and 32-bit true color with alpha bitmaps. The logical order of the pixel array is not important here, so the code just goes through each pixel in the order they appear. For 16-bit bitmaps, two common formats are supported. The code needs to extract the RGB channels, convert them to 8 bits each, call the color transformation routine, and pack the results back into a 16-bit WORD. A 24-bit bitmap is very easy to handle. For a 32-bit bitmap, its alpha channel is untouched.



    Any other rare DIB formats, like JPEG or PNG compressed bitmaps, or bitmaps with unusual bit fields, are not supported by the currently implemented ColorTransform routine.



    Converting Bitmaps to Grayscale


    The commonly used formula for converting color in RGB space to grayscale is





    For computer implementation, we would like to implement the conversion without any floating-point computation. Based on the ColorTransform template, here is our RGB-bitmap to grayscale-bitmap conversion method.





    // 0.299 * red + 0.587 * green + 0.114 * blue
    inline void MaptoGray(BYTE & red, BYTE & green, BYTE & blue)
    {
    red = ( red * 77 + green * 150 + blue * 29 + 128 ) / 256;
    green = red;
    blue = red;
    }

    class KImage : public KDIB
    {
    public:
    bool ToGreyScale(void);
    ...
    };

    bool KImage::ToGreyScale(void)
    {
    return ColorTransform(this, MaptoGray);
    }


    A new class KImage is derived from the KDIB class to encapsulate image-processing algorithms developed in this chapter. The KImage class has no extra member variables. Its only method shown here is ToGreyScale. More methods will be added later in this chapter.



    The KImage::ToGreyScale method transforms the current color DIB to a grayscale DIB. It simply calls the ColorTransform template function with the MaptoGray routine as the color transformation routine. MaptoGray uses integer operation to calculate the lightness of a color and assign it to all three RGB channels.



    In a debug build, MaptoGray is compiled as a subroutine and its pointer is passed to ColorTransform. In a release build, all calls to MaptoGray are in-lined to get the best performance.




    Gamma Correction


    Image displaying suffers from photometric distortions caused by the nonlinear response of display devices to lightness. The photometric response of a displaying device is known as the gamma response characteristic. Display monitors for different operating systems use different gammas. When an image prepared on a Macintosh screen is displayed on a PC screen, it normally looks too dark. On the other hand, an image downloaded from a PC server to a Macintosh machine may look too bright. To compensate for these differences, the gamma of the image needs to be corrected.



    Gamma correction is normally done in the three RGB channels independently. Three arrays of 256 bytes each are precalculated and passed to either the software gamma transformer or the hardware display card. Each of the three arrays is applied to one of the channels.



    Gamma correction can be easily implemented using the ColorTransform template function.





    BYTE redGammaRamp[256];
    BYTE greenGammaRamp[256];
    BYTE blueGammaRamp[256];

    inline void MapGamma(BYTE & red, BYTE & green, BYTE & blue)
    {
    red = redGammaRamp[red];
    green = greenGammaRamp[green];
    blue = blueGammaRamp[blue];
    }

    BYTE gamma(double g, int index)
    {
    return min(255, (int) ( (255.0 * pow(index/255.0, 1.0/g)) + 0.5 ) );
    }

    bool KImage::GammaCorrect(double redgamma, double greengamma,
    double bluegamma)
    {
    for (int i=0; i<256; i++)
    {
    redGammaRamp[i] = gamma( redgamma, i);
    greenGammaRamp[i] = gamma(greengamma, i);
    blueGammaRamp[i] = gamma( bluegamma, i);
    }

    return ColorTransform(this, MapGamma);
    }


    The user level routine provided here is KDIB::GammaCorrect. It accepts three independent gamma values, which normally range between 0.2 and 5.0. The routine pre-calculates three gamma ramps for each of the RGB channels, according to the definition of gamma. It then calls ColorTransform with the MapGamma routine as the color transformer. MapGamma does a simple table lookup for each pixel.



    A gamma correction with gamma equal to 1.0 is an identity color transformation. Gamma less than one makes a picture look �darker,� and gamma larger than one makes a picture look �lighter.�



    If you apply a gamma correction of 2.2 to images prepared on a Macintosh, they will look exactly as they originally appeared on their creator's screen. Figure 12-2 shows a tiger picture with the wrong gamma and its gamma-corrected version.




    Figure 12-2. Gamma correction.


    The table lookup mechanism implemented by MapGamma can also be used to adjust color according to other criteria. Actually, the only condition is that the RGB channels are independent of each other. For example, you can define a red Gamma Ramp to reduce the red channel by 10%, while leaving the other two as identity transformations.



    Win32 GDI supports setting a graphics device's gamma ramp if the hardware and device driver supports downloadable gamma ramps. The related function is SetDeviceGammaRamp, which is part of ICM 2.0. DirectDraw also supports gamma ramps through the IDirectDrawGammaControl interface. Newer PC hardware should all support downloadable gamma ramps.







    < BACK  NEXT >





    Chapter 7. Ajax Tags










    Chapter 7. Ajax Tags


    Writing Ajaxian code over and over can be tedious and error-prone. Although many libraries with a lot of reusable code are available, you may develop some custom features that you want to use repeatedly throughout your applications. In that case, you can encapsulate the functionality in a JSP tag for easy reuse. Using tag libraries will save you time and enhance the maintainability of your code. If you fix a bug in a tag library, you can easily propagate the change to all of your code: instead of rewriting the code in every application, merely drop your new library into the deploy directory.












    6.1 Introduction




    I l@ve RuBoard










    6.1 Introduction



    This chapter covers sorting, an
    operation that is extremely important for controlling how MySQL
    displays results from SELECT statements. Sorting
    is performed by adding an ORDER
    BY clause to a query. Without such a clause, MySQL
    is free to return rows in any order, so sorting helps bring order to
    disorder and make query results easier to examine and understand.
    (Sorting also is performed implicitly when you use a
    GROUP BY clause, as discussed
    in Recipe 7.14.)



    One of the tables used for quite a few examples in this chapter is
    driver_log, a table that contains columns for
    recording daily mileage logs for a set of truck drivers:



    mysql> SELECT * FROM driver_log;
    +--------+-------+------------+-------+
    | rec_id | name | trav_date | miles |
    +--------+-------+------------+-------+
    | 1 | Ben | 2001-11-30 | 152 |
    | 2 | Suzi | 2001-11-29 | 391 |
    | 3 | Henry | 2001-11-29 | 300 |
    | 4 | Henry | 2001-11-27 | 96 |
    | 5 | Ben | 2001-11-29 | 131 |
    | 6 | Henry | 2001-11-26 | 115 |
    | 7 | Suzi | 2001-12-02 | 502 |
    | 8 | Henry | 2001-12-01 | 197 |
    | 9 | Ben | 2001-12-02 | 79 |
    | 10 | Henry | 2001-11-30 | 203 |
    +--------+-------+------------+-------+


    Many other examples use the mail table (first seen
    in earlier chapters):



    mysql> SELECT * FROM mail;
    +---------------------+---------+---------+---------+---------+---------+
    | t | srcuser | srchost | dstuser | dsthost | size |
    +---------------------+---------+---------+---------+---------+---------+
    | 2001-05-11 10:15:08 | barb | saturn | tricia | mars | 58274 |
    | 2001-05-12 12:48:13 | tricia | mars | gene | venus | 194925 |
    | 2001-05-12 15:02:49 | phil | mars | phil | saturn | 1048 |
    | 2001-05-13 13:59:18 | barb | saturn | tricia | venus | 271 |
    | 2001-05-14 09:31:37 | gene | venus | barb | mars | 2291 |
    | 2001-05-14 11:52:17 | phil | mars | tricia | saturn | 5781 |
    | 2001-05-14 14:42:21 | barb | venus | barb | venus | 98151 |
    | 2001-05-14 17:03:01 | tricia | saturn | phil | venus | 2394482 |
    | 2001-05-15 07:17:48 | gene | mars | gene | saturn | 3824 |
    | 2001-05-15 08:50:57 | phil | venus | phil | venus | 978 |
    | 2001-05-15 10:25:52 | gene | mars | tricia | saturn | 998532 |
    | 2001-05-15 17:35:31 | gene | saturn | gene | mars | 3856 |
    | 2001-05-16 09:00:28 | gene | venus | barb | mars | 613 |
    | 2001-05-16 23:04:19 | phil | venus | barb | venus | 10294 |
    | 2001-05-17 12:49:23 | phil | mars | tricia | saturn | 873 |
    | 2001-05-19 22:21:51 | gene | saturn | gene | venus | 23992 |
    +---------------------+---------+---------+---------+---------+---------+


    Other tables are used occasionally as well. You can create most of
    them with the scripts found in the tables
    directory of the recipes distribution. The
    baseball1 directory contains instructions for
    creating the tables used in the examples relating to the
    baseball1.com baseball database.









      I l@ve RuBoard



      CRITICAL SKILL 6.5 Handle Error Conditions in PL/SQL


      Team Fly 


      Page 217



      CRITICAL SKILL 6.5
      Handle Error Conditions in PL/SQL



      As we have seen in the previous section, bad things happen to good programs. However, you also have to deal with bad or problematic data as well. To deal with problems during the processing of data, PL/SQL provides us with the robust ability to handle these types of errors. We call this type of program code exception handling.



      To raise an error from within a PL/SQL program, use the built-in function named raise_application_error. The function requires two arguments. One is for the error number. This number must be between −20000 and −20999. The second argument is the error that you want the user to see.



      As with all exception handling, this program code is placed into the EXCEPTION section of your PL/SQL program. Thus, our program structure will now be




      BEGIN
      -- Put Program Here
      EXCEPTION
      -- Put exception handlers here
      END;
      /


      Table 6-3 looks at some of the most common errors that Oracle helps you handle.



      NOTE
      You must always make the ''Others" error handle the last one in your program, since Oracle will not process any exception handles after this one.









      Exception Name


      Explanation


      Oracle Error


      No_data_found


      When a select statement returns no rows, this error may be raised. It usually occurs when you use an implicit cursor and perform a SELECT INTO.


      ORA-01403


      Too_many_rows


      When a case that should only return a single row returns multiple rows, this exception is raised.


      ORA-01422


      Dup_val_on_index


      This exception is raised when you try to insert a record into a table that has a primary key on it and the record that you are inserting is a duplicate of one that already exists in the table.


      ORA-00001



      Team Fly 

      Busses and Attachments













      Busses and Attachments

      Every device in the system is attached to some other device. We saw an example of this in Chapter 11, with the dmassage program that generated a simple drawing of what hardware was attached to which bus. Not all systems have all busses; while OpenBSD supports PCI devices, for example, it runs just fine on ISA-only systems.




      mainbus0


      On i386 hardware everything sits on top of the main bus, called "mainbus0." This is the foundation of your kernel. Your SCSI hard disk might be on top of the SCSI bus, which sits on top of a SCSI card, which is plugged into the PCI bus, but that PCI bus will be attached to the main bus.





      Connection Configuration


      The kernel must know how these busses and cards hook together. You'll see quite a few entries in your copied kernel configuration that look like this.




      isa0 1 at mainbus0
      isa0 2 at pcib?


      Older computers just have an ISA bus that is 1 directly attached to the main system bus, and we must tell the kernel how to recognize that configuration. On PCI-based computers, the ISA bus is frequently 2 plugged into the PCI-ISA bridge instead of directly to the main bus. (This is a matter of hardware design, not kernel design.) With the above configuration, if the ISA bus is in either of these locations the kernel will find it. If you have some special hardware with the ISA bus attached elsewhere, this kernel will not find it.


      Also, note the device numbers. This configuration is for ISA bus number zero. As systems only have one ISA bus, this is perfectly acceptable. A system can have multiple PCI buses, however. That's why the second configuration line has a question mark by the device number for the PCI bus; this entry will match any PCI bus. Some device drivers must have a hard-coded number, while others will accept a question mark instead. Generally, non-Plug-and-Play ISA cards must have a hard-coded device number.


      You can follow the hardware connections through the kernel configuration. We previously mentioned how a simple SCSI disk can live at the end of a long chain of hardware. Let's see how. A SCSI disk uses the "sd" driver.





      sd* 1 at 2 scsibus? target ? lun ? # SCSI disk drives


      Here, we have 1 any number of SCSI disks. They can be attached to 2 any SCSI bus.


      If you have an AdvanSys 1200B UltraSCSI controller, it'll use the adv driver. If you search your kernel configuration for this driver, you'll find it easily.




      1 adv* at pci? 3 dev ? function ? # AdvanSys 1200A/B and ULTRA SCSI
      2 scsibus* at adv?


      The 1 first entry tells the kernel to recognize AdvanSys card. The kernel will also attach a 2 SCSI bus to this card, when found. A check of the GENERIC kernel configuration shows that the kernel is configured to attach a SCSI bus to any SCSI card. The adv card expects to be plugged into a 3 PCI bus. Where does our PCI bus come from? Well, GENERIC has the following entries for the PCI bus.





      pci* at mainbus0 bus ?
      pci* at ppb? bus ?
      pci* at pchb? bus ?


      Depending on which sort of PCI bus you have and how it is attached to the system, you might be done. You could continue tracking these devices back, and see how everything hooks together, but you should have the idea by now.


      For our SCSI disk to work, every step of the attachment chain must be in the kernel configuration. You can have the drivers for the SCSI disk and SCSI card in your kernel, but if you don't have the entry for the SCSI bus to connect the two, the disk won't work. Every device must be able to find the devices beneath it. After all, if your kernel can't find the PCI bus, it won't find the devices attached to it!












      Summary






















       Print  
       E-Mail
       
       Add
      Note    Add
      Bookmark
         














      JSTL:
      JSP Standard Tag Library Kick Start
      By
      Jeff Heaton

      Table
      of Contents
      Chapter 5.  Collections,
      Loops, and Iterators









      Summary


      In this chapter, we showed you how to use
      iterators. Iteration is one of the most important concepts in
      Web programming. As you progress through the remaining
      chapters in this book, you will use iterations to process
      other types of data, such as the results from an SQL
      database.


      This chapter also showed that you can use
      iterators to perform basic string processing. In the next
      chapter, you will learn how to properly format data for
      display using JSTL's formatting tag library.











         Print  
         E-Mail
         
         Add
        Note    Add
        Bookmark
           




        Top

        [0672324504/ch05lev1sec4]