dib2jpeg.txt
上传用户:jinjie988
上传日期:2007-01-03
资源大小:4k
文件大小:12k
源码类别:

图片显示

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////Example of use:
  2. /////////////////////////////////////////////////////////////void MakeJpeg(){
  3.     CBitmap  cBitmap;    BITMAP   bm;    CString  csMsg = "";
  4.     cBitmap.LoadBitmap(IDB_TEST);    cBitmap.GetBitmap(&bm);
  5.     HANDLE  hDib = DDBToDIB((HBITMAP)cBitmap,
  6.                              BI_RGB,
  7.                              NULL);  //Use default palette
  8.     //Turn DIB into JPEG file    if (hDib != NULL)    {
  9.         if (!JpegFromDib(hDib,                         100,   //Quality setting
  10.                          "test.jpg",                         &csMsg))        {
  11.             AfxMessageBox(csMsg);        }        else
  12.             AfxMessageBox("test.jpg created");        ::GlobalFree(hDib);    }
  13.     else        AfxMessageBox("Failed to load IDB_TEST");}
  14. ////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////Header file code
  16. ////////////////////////////////////////////////////////////
  17. ////////////////////////////////////////////////////////////
  18. //In the relevant header file (up near the top):#include "jpeglib.h"
  19. BOOL JpegFromDib(HANDLE     hDib,     //Handle to DIB
  20.                  int        nQuality, //JPEG quality (0-100)
  21.                  CString    csJpeg,   //Pathname to target jpeg file
  22.                  CString*   pcsMsg);  //Error msg to return
  23. BOOL BuildSamps(HANDLE                      hDib,
  24.                 int                         nSampsPerRow,
  25.                 struct jpeg_compress_struct cinfo,
  26.                 JSAMPARRAY                  jsmpArray,
  27.                 CString*                    pcsMsg);
  28. RGBQUAD QuadFromWord(WORD b16);
  29. ////////////////////////////////////////////////////////////
  30. //////////////////////////////////////////////////////////////Source file code
  31. ////////////////////////////////////////////////////////////
  32. ////////////////////////////////////////////////////////////extern "C"{
  33. #include "jpeglib.h"}         #include struct ima_error_mgr{
  34.   struct  jpeg_error_mgr pub; //"public" fields
  35.   jmp_buf setjmp_buffer;   //for return to caller};
  36. ////////////////////////////////////////////////////////////////////////////
  37. //This function takes the contents of a DIB//and turns it into a JPEG file.//
  38. //The DIB may be monochrome, 16-color, 256-color, or 24-bit color.//
  39. //Any functions or data items beginning with "jpeg_" belong to jpeg.lib,
  40. //and are not included here.//
  41. //The function assumes 3 color components per pixel.
  42. /////////////////////////////////////////////////////////////////////////////
  43. BOOL JpegFromDib(HANDLE     hDib,     //Handle to DIB
  44.                  int        nQuality, //JPEG quality (0-100)
  45.                  CString    csJpeg,   //Pathname to jpeg file
  46.                  CString*   pcsMsg)   //Error msg to return{
  47.     //Basic sanity checks...    if (nQuality < 0 || nQuality > 100 ||
  48.         hDib   == NULL ||        pcsMsg == NULL ||        csJpeg == "")    {
  49.         if (pcsMsg != NULL)            *pcsMsg = "Invalid input data";
  50.         return FALSE;    }    *pcsMsg = "";
  51.     LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;    byte *buf2 = 0;
  52.     //Use libjpeg functions to write scanlines to disk in JPEG format
  53.     struct jpeg_compress_struct cinfo;    struct jpeg_error_mgr       jerr;
  54.     FILE*      pOutFile;     //Target file 
  55.     int        nSampsPerRow; //Physical row width in image buffer 
  56.     JSAMPARRAY jsmpArray;    //Pixel RGB buffer for JPEG file
  57.     cinfo.err = jpeg_std_error(&jerr); //Use default error handling (ugly!)
  58.     jpeg_create_compress(&cinfo);
  59.     if ((pOutFile = fopen(csJpeg, "wb")) == NULL)    {
  60.         *pcsMsg = "Cannot open "; *pcsMsg += csJpeg;
  61.         jpeg_destroy_compress(&cinfo);        return FALSE;    }
  62.     jpeg_stdio_dest(&cinfo, pOutFile);
  63.     cinfo.image_width      = lpbi->biWidth;  //Image width and height, in pixels 
  64.     cinfo.image_height     = lpbi->biHeight;
  65.     cinfo.input_components = 3;              //Color components per pixel
  66.                                              //(RGB_PIXELSIZE - see jmorecfg.h)
  67.     cinfo.in_color_space   = JCS_RGB;       //Colorspace of input image
  68.     jpeg_set_defaults(&cinfo);    jpeg_set_quality(&cinfo,
  69.                      nQuality, //Quality: 0-100 scale
  70.                      TRUE);    //Limit to baseline-JPEG values
  71.     jpeg_start_compress(&cinfo, TRUE);    //JSAMPLEs per row in output buffer
  72.     nSampsPerRow = cinfo.image_width * cinfo.input_components; 
  73.     //Allocate array of pixel RGB values
  74.     jsmpArray = (*cinfo.mem->alloc_sarray)
  75.                 ((j_common_ptr) &cinfo,                 JPOOL_IMAGE,
  76.                  nSampsPerRow,                 cinfo.image_height);
  77.     if (DibToSamps(hDib,                   nSampsPerRow,
  78.                    cinfo,                   jsmpArray,
  79.                    pcsMsg))    {
  80.         //Write the array of scan lines to the JPEG file
  81.         (void)jpeg_write_scanlines(&cinfo,
  82.                                    jsmpArray,
  83.                                    cinfo.image_height);    }
  84.     jpeg_finish_compress(&cinfo); //Always finish    fclose(pOutFile);
  85.     jpeg_destroy_compress(&cinfo); //Free resources    if (*pcsMsg != "")
  86.         return FALSE;    else        return TRUE;}
  87. ////////////////////////////////////////////////////////////////
  88. //This function fills a jsmpArray with the RGB values//for the CBitmap.//
  89. //It has been improved to handle all legal bitmap formats.//
  90. //A jsmpArray is a big array of RGB values, 3 bytes per value.//
  91. //Note that rows of pixels are processed bottom to top:
  92. //The data in the jsamp array must be arranged top to bottom.
  93. ////////////////////////////////////////////////////////////////
  94. BOOL DibToSamps(HANDLE                      hDib,
  95.                 int                         nSampsPerRow,
  96.                 struct jpeg_compress_struct cinfo,
  97.                 JSAMPARRAY                  jsmpPixels,
  98.                 CString*                    pcsMsg){   //Sanity...
  99.    if (hDib == NULL    ||     nSampsPerRow <= 0 || pcsMsg == NULL)    { 
  100.      if (pcsMsg !=NULL)         *pcsMsg="Invalid input data"; 
  101.      return FALSE;    }    int r=0, p=0, q=0, b=0, n=0, 
  102.        nUnused=0, nBytesWide=0, nUsed=0, nLastBits=0, nLastNibs=0, nCTEntries=0,
  103.        nRow=0, nByte=0, nPixel=0;   BYTE bytCTEnt=0;
  104.    LPBITMAPINFOHEADER pbBmHdr= (LPBITMAPINFOHEADER)hDib; //The bit count tells you the format of the bitmap: //Decide how many entries will be in the color table (if any) 
  105.    switch (pbBmHdr->biBitCount)   {      case 1:
  106.          nCTEntries = 2;   //Monochrome         break;      case 4:
  107.          nCTEntries = 16;  //16-color         break;      case 8:
  108.          nCTEntries = 256; //256-color         break;      case 16:
  109.       case 24:      case 32:         nCTEntries = 0;   //No color table needed
  110.          break;      default:         *pcsMsg = "Invalid bitmap bit count";
  111.          return FALSE; //Unsupported format   }
  112.    //Point to the color table and pixels
  113.    DWORD     dwCTab = (DWORD)pbBmHdr + pbBmHdr->biSize;
  114.    LPRGBQUAD pCTab  = (LPRGBQUAD)(dwCTab);   LPSTR     lpBits = (LPSTR)pbBmHdr +
  115.                       (WORD)pbBmHdr->biSize +
  116.                       (WORD)(nCTEntries * sizeof(RGBQUAD));
  117.    //Different formats for the image bits
  118.    LPBYTE   lpPixels = (LPBYTE)  lpBits;   RGBQUAD* pRgbQs   = (RGBQUAD*)lpBits;
  119.    WORD*    wPixels  = (WORD*)   lpBits;
  120.    //Set up the jsamps according to the bitmap's format.
  121.    //Note that rows are processed bottom to top, because
  122.    //that's how bitmaps are created.   switch (pbBmHdr->biBitCount)   {
  123.       case 1:         nUsed      = (pbBmHdr->biWidth + 7) / 8;
  124.          nUnused    = (((nUsed + 3) / 4) * 4) - nUsed;
  125.          nBytesWide = nUsed + nUnused;
  126.          nLastBits  = 8 - ((nUsed * 8) - pbBmHdr->biWidth);
  127.          for (r=0; r < pbBmHdr->biHeight; r++)         {
  128.             for (p=0,q=0; p < nUsed; p++)             { 
  129.                nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
  130.                nByte =  nRow + p;
  131.                int nBUsed = (p <(nUsed 1)) ? 8 : nLastBits; for(b=0; b < nBUsed;b++) 
  132.                {                   bytCTEnt = lpPixels[nByte] << b; 
  133.                   bytCTEnt = bytCTEnt >> 7;
  134.                   jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
  135.                   jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
  136.                   jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
  137.                   q += 3;               }            }         }         break;
  138.       case 4:         nUsed      = (pbBmHdr->biWidth + 1) / 2;
  139.          nUnused    = (((nUsed + 3) / 4) * 4) - nUsed;
  140.          nBytesWide = nUsed + nUnused;
  141.          nLastNibs  = 2 - ((nUsed * 2) - pbBmHdr->biWidth);
  142.          for (r=0; r < pbBmHdr->biHeight;r++)         {
  143.             for (p=0,q=0; p < nUsed;p++)             { 
  144.                nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
  145.                nByte = nRow + p;               int nNibbles = (p  > (4-(n*4));
  146.                   jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
  147.                   jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
  148.                   jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
  149.                   q += 3;               }            }         }         break;
  150.       default:      case 8: //Each byte is a pointer to a pixel color
  151.          nUnused = (((pbBmHdr->biWidth + 3) / 4) * 4) -
  152.                    pbBmHdr->biWidth;
  153.          for (r=0;r < pbBmHdr->biHeight; r++)         {
  154.             for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)            {
  155.                nRow   = (pbBmHdr->biHeight-r-1) * (pbBmHdr->biWidth + nUnused);
  156.                nPixel =  nRow + p;
  157.                jsmpPixels[r][q+0] = pCTab[lpPixels[nPixel]].rgbRed;
  158.                jsmpPixels[r][q+1] = pCTab[lpPixels[nPixel]].rgbGreen;
  159.                jsmpPixels[r][q+2] = pCTab[lpPixels[nPixel]].rgbBlue;
  160.             }         }         break;
  161.       case 16: //Hi-color (16 bits per pixel)
  162.          for (r=0;r < pbBmHdr->biHeight; r++)         {
  163.             for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)            {
  164.                nRow    = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth;
  165.                nPixel  = nRow + p;
  166.                RGBQUAD quad = QuadFromWord(wPixels[nPixel]);
  167.                jsmpPixels[r][q+0] = quad.rgbRed;
  168.                jsmpPixels[r][q+1] = quad.rgbGreen;
  169.                jsmpPixels[r][q+2] = quad.rgbBlue;            }         }
  170.          break;      case 24:         nBytesWide =  (pbBmHdr->biWidth*3);
  171.          nUnused    =  (((nBytesWide + 3) / 4) * 4) -
  172.                        nBytesWide;         nBytesWide += nUnused;
  173.          for (r=0;r biHeight;r++)         {
  174.             for (p=0,q=0;p < (nBytesWide-nUnused); p+=3,q+=3)            { 
  175.                nRow = (pbBmHdr->biHeight-r-1) * nBytesWide;
  176.                nPixel  = nRow + p;
  177.                jsmpPixels[r][q+0] = lpPixels[nPixel+2]; //Red
  178.                jsmpPixels[r][q+1] = lpPixels[nPixel+1]; //Green
  179.                jsmpPixels[r][q+2] = lpPixels[nPixel+0]; //Blue            }
  180.          }         break;      case 32:
  181.          for (r=0; r < pbBmHdr->biHeight; r++)         {
  182.             for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)            {
  183.                nRow    = (pbBmHdr->biHeight-r-1) *
  184.                           pbBmHdr->biWidth;               nPixel  = nRow + p;
  185.                jsmpPixels[r][q+0] = pRgbQs[nPixel].rgbRed;
  186.                jsmpPixels[r][q+1] = pRgbQs[nPixel].rgbGreen;
  187.                jsmpPixels[r][q+2] = pRgbQs[nPixel].rgbBlue;            }
  188.          }         break;   }   //end switchreturn TRUE;} 
  189. //////////////////////////////////////////This function turns a 16-bit pixel
  190. //into an RGBQUAD value.////////////////////////////////////////
  191. RGBQUAD QuadFromWord(WORD b16){   BYTE bytVals[] =   {
  192.      0,  16, 24, 32,  40, 48, 56, 64,     72, 80, 88, 96, 104,112,120,128,
  193.      136,144,152,160,168,176,184,192,     200,208,216,224,232,240,248,255   };
  194.    WORD wR = b16;   WORD wG = b16;   WORD wB = b16;   wR <<= 1; wR >>= 11;
  195.    wG <<= 6; wG >>= 11;   wB <<= 11; wB >>= 11;   RGBQUAD rgb;
  196.    rgb.rgbReserved = 0;   rgb.rgbBlue     = bytVals[wB];
  197.    rgb.rgbGreen    = bytVals[wG];   rgb.rgbRed      = bytVals[wR];   return rgb;
  198. }