home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICM.C
- //
- // helper routines for compressing/decompressing/and choosing compressors.
- //
- // in order to use the ICChooseCompressor() function you need to include
- // ICM.DLG into your apps resource file.
- //
- // (C) Copyright Microsoft Corp. 1991, 1992, 1993. All rights reserved.
- //
- // You have a royalty-free right to use, modify, reproduce and
- // distribute the Sample Files (and/or any modified version) in
- // any way you find useful, provided that you agree that
- // Microsoft has no warranty obligations or liability for any
- // Sample Application Files.
- //
- // If you did not get this from Microsoft Sources, then it may not be the
- // most current version. This sample code in particular will be updated
- // and include more documentation.
- //
- // Sources are:
- // CompuServe: WINSDK forum, MDK section.
- // Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include <windows.h>
- #include <windowsx.h>
- #include <compman.h>
- #include "icm.h"
-
- #include "icm.dlg"
-
- // C6 needs this redefined.
- #undef GlobalFreePtr
- #define GlobalFreePtr(p) (BOOL)GlobalFree(GlobalPtrHandle(p))
-
- ///////////////////////////////////////////////////////////////////////////////
- // DIB Macros
- ///////////////////////////////////////////////////////////////////////////////
-
- #define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
- #define DibWidthBytes(lpbi) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)((lpbi)->biBitCount))
-
- #define DibSizeImage(lpbi) ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)((lpbi)->biHeight))
- #define DibSize(lpbi) ((lpbi)->biSize + (lpbi)->biSizeImage + (int)(lpbi)->biClrUsed * sizeof(RGBQUAD))
-
- #define DibPtr(lpbi) (LPVOID)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed)
- #define DibColors(lpbi) ((LPRGBQUAD)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
-
- #define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
- ? (int)(1 << (int)(lpbi)->biBitCount) \
- : (int)(lpbi)->biClrUsed)
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICCompressDecompressImage
- //
- // compresses or decompresses a given image.
- //
- // input:
- // hic compressor to use, if NULL is specifed a
- // compressor will be located that can handle the conversion.
- // uiFlags flags (not used, must be 0)
- // lpbiIn input DIB format
- // lpBits input DIB bits
- // lpbiOut output format, if NULL is specifed the default
- // format choosen be the compressor will be used.
- // lQuality the reqested compression quality
- //
- // returns:
- // a HANDLE to the converted image. The handle is a DIB in CF_DIB
- // format, ie a packed DIB. The caller is responsible for freeing
- // the memory. NULL is returned if error.
- //
- ///////////////////////////////////////////////////////////////////////////////
- HANDLE FAR ICCompressDecompressImage(
- HIC hic, // compressor (NULL if any will do)
- UINT uiFlags, // silly flags
- LPBITMAPINFOHEADER lpbiIn, // input DIB format
- LPVOID lpBits, // input DIB bits
- LPBITMAPINFOHEADER lpbiOut, // output format (NULL => default)
- LONG lQuality) // the reqested quality
- {
- HANDLE h;
-
- if (lpbiIn->biCompression == 0)
- (h = ICCompressImage (hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ||
- (h = ICDecompressImage(hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ;
- else
- (h = ICDecompressImage(hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ||
- (h = ICCompressImage (hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ;
-
- return h;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICCompressImage
- //
- // compresses a given image.
- //
- // input:
- // hic compressor to use, if NULL is specifed a
- // compressor will be located that can handle the conversion.
- // uiFlags flags (not used, must be 0)
- // lpbiIn input DIB format
- // lpBits input DIB bits
- // lpbiOut output format, if NULL is specifed the default
- // format choosen be the compressor will be used.
- // lQuality the reqested compression quality
- //
- // returns:
- // a HANDLE to the converted image. The handle is a DIB in CF_DIB
- // format, ie a packed DIB. The caller is responsible for freeing
- // the memory. NULL is returned if error.
- //
- ///////////////////////////////////////////////////////////////////////////////
- HANDLE FAR ICCompressImage(
- HIC hic, // compressor (NULL if any will do)
- UINT uiFlags, // silly flags
- LPBITMAPINFOHEADER lpbiIn, // input DIB format
- LPVOID lpBits, // input DIB bits
- LPBITMAPINFOHEADER lpbiOut, // output format (NULL => default)
- LONG lQuality) // the reqested quality
- {
- LONG l;
- BOOL fNuke;
- DWORD dwFlags = 0;
- DWORD ckid = 0;
-
- LPBITMAPINFOHEADER lpbi=NULL;
-
- //
- // either locate a compressor or use the one supplied.
- //
- if (fNuke = (hic == NULL))
- {
- hic = ICLocate(ICTYPE_VIDEO, 0L, lpbiIn, lpbiOut, ICMODE_COMPRESS);
-
- if (hic == NULL)
- return NULL;
- }
-
- //
- // make sure the found compressor can handle this format.
- //
- if (ICCompressQuery(hic, lpbiIn, NULL) != ICERR_OK)
- goto error;
-
- //
- // now make a DIB header big enought to hold the ouput format
- //
- l = ICCompressGetFormatSize(hic, lpbiIn);
-
- if (l <= 0)
- goto error;
-
- lpbi = (LPVOID)GlobalAllocPtr(GHND, l + 256*sizeof(RGBQUAD));
-
- if (lpbi == NULL)
- goto error;
-
- //
- // if the compressor likes the passed format, use it else use the default
- // format of the compressor.
- //
- if (lpbiOut == NULL || ICCompressQuery(hic, lpbiIn, lpbiOut) != ICERR_OK)
- ICCompressGetFormat(hic, lpbiIn, lpbi);
- else
- hmemcpy(lpbi, lpbiOut, lpbiOut->biSize + lpbiOut->biClrUsed * sizeof(RGBQUAD));
-
- lpbi->biSizeImage = ICCompressGetSize(hic, lpbiIn, lpbi);
- lpbi->biClrUsed = DibNumColors(lpbi);
-
- //
- // now resize the DIB to be the maximal size.
- //
- lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi), 0);
-
- if (lpbi == NULL)
- goto error;
-
- //
- // now compress it.
- //
- if (ICCompressBegin(hic, lpbiIn, lpbi) != ICERR_OK)
- goto error;
-
- if (lpBits == NULL)
- lpBits = DibPtr(lpbiIn);
-
- if (lQuality == ICQUALITY_DEFAULT)
- lQuality = ICGetDefaultQuality(hic);
-
- l = ICCompress(hic,
- 0, // flags
- lpbi, // output format
- DibPtr(lpbi), // output data
- lpbiIn, // format of frame to compress
- lpBits, // frame data to compress
- &ckid, // ckid for data in AVI file
- &dwFlags, // flags in the AVI index.
- 0, // frame number of seq.
- 0, // reqested size in bytes. (if non zero)
- lQuality, // quality
- NULL, // format of previous frame
- NULL); // previous frame
-
- if (l < ICERR_OK)
- goto error;
-
- if (ICCompressEnd(hic) != ICERR_OK)
- goto error;
-
- //
- // now resize the DIB to be the real size.
- //
- lpbi = (LPVOID)GlobalReAllocPtr(lpbi, DibSize(lpbi), 0);
-
- //
- // all done return the result to the caller
- //
- if (fNuke)
- ICClose(hic);
-
- return GlobalPtrHandle(lpbi);
-
- error:
- if (lpbi)
- GlobalFreePtr(lpbi);
-
- if (fNuke)
- ICClose(hic);
-
- return NULL;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICDecompressImage
- //
- // decompresses a given image.
- //
- // input:
- // hic compressor to use, if NULL is specifed a
- // compressor will be located that can handle the conversion.
- // uiFlags flags (not used, must be 0)
- // lpbiIn input DIB format
- // lpBits input DIB bits
- // lpbiOut output format, if NULL is specifed the default
- // format choosen be the compressor will be used.
- // lQuality the reqested compression quality
- //
- // returns:
- // a HANDLE to the converted image. The handle is a DIB in CF_DIB
- // format, ie a packed DIB. The caller is responsible for freeing
- // the memory. NULL is returned if error.
- //
- ///////////////////////////////////////////////////////////////////////////////
- HANDLE FAR ICDecompressImage(
- HIC hic, // compressor (NULL if any will do)
- UINT uiFlags, // silly flags
- LPBITMAPINFOHEADER lpbiIn, // input DIB format
- LPVOID lpBits, // input DIB bits
- LPBITMAPINFOHEADER lpbiOut, // output format (NULL => default)
- LONG lQuality) // the reqested quality
- {
- LONG l;
- BOOL fNuke;
- DWORD dwFlags = 0;
- DWORD ckid = 0;
-
- LPBITMAPINFOHEADER lpbi=NULL;
-
- //
- // either locate a compressor or use the one supplied.
- //
- if (fNuke = (hic == NULL))
- {
- hic = ICLocate(ICTYPE_VIDEO, 0L, lpbiIn, lpbiOut, ICMODE_DECOMPRESS);
-
- if (hic == NULL)
- return NULL;
- }
-
- //
- // make sure the found compressor can handle this format.
- //
- if (ICDecompressQuery(hic, lpbiIn, NULL) != ICERR_OK)
- goto error;
-
- //
- // make a DIB header big enought to hold the ouput format
- //
- l = ICDecompressGetFormatSize(hic, lpbiIn);
-
- if (l <= 0)
- goto error;
-
- lpbi = (LPVOID)GlobalAllocPtr(GHND, l + 256*sizeof(RGBQUAD));
-
- if (lpbi == NULL)
- goto error;
-
- //
- // if the compressor likes the passed format, use it else use the default
- // format of the compressor.
- //
- if (lpbiOut == NULL || ICDecompressQuery(hic, lpbiIn, lpbiOut) != ICERR_OK)
- ICDecompressGetFormat(hic, lpbiIn, lpbi);
- else
- hmemcpy(lpbi, lpbiOut, lpbiOut->biSize + lpbiOut->biClrUsed * sizeof(RGBQUAD));
-
- //
- // for decompress make sure the palette (ie color table) is correct
- //
- if (lpbi->biBitCount <= 8)
- ICDecompressGetPalette(hic, lpbiIn, lpbi);
-
- lpbi->biSizeImage = DibSizeImage(lpbi); // ICDecompressGetSize(hic, lpbi);
- lpbi->biClrUsed = DibNumColors(lpbi);
-
- //
- // now resize the DIB to be the right size.
- //
- lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi),0);
-
- if (lpbi == NULL)
- goto error;
-
- //
- // now decompress it.
- //
- if (ICDecompressBegin(hic, lpbiIn, lpbi) != ICERR_OK)
- goto error;
-
- if (lpBits == NULL)
- lpBits = DibPtr(lpbiIn);
-
- l = ICDecompress(hic,
- 0, // flags
- lpbiIn, // format of frame to decompress
- lpBits, // frame data to decompress
- lpbi, // output format
- DibPtr(lpbi)); // output data
-
- if (l < ICERR_OK)
- goto error;
-
- if (ICDecompressEnd(hic) != ICERR_OK)
- goto error;
-
- //
- // now resize the DIB to be the real size.
- //
- lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi),0);
-
- //
- // all done return the result to the caller
- //
- if (fNuke)
- ICClose(hic);
-
- return GlobalPtrHandle(lpbi);
-
- error:
- if (lpbi)
- GlobalFreePtr(lpbi);
-
- if (fNuke)
- ICClose(hic);
-
- return NULL;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICChooseCompressorStuff
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- static BOOL CALLBACK ICChooseCompressorDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
- typedef struct {
- DWORD fccType;
- UINT uiFlags;
- LPVOID pvIn;
- LPVOID lpData;
- HIC hic;
- LONG lQuality;
- ICINFO icinfo;
- } ICChooseCompressorStuff, FAR *PICChooseCompressorStuff;
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICChooseCompressor
- //
- // Brings up a dialog and allows the user to choose a compression
- // method and a quality level. all compressors in the system are
- // displayed and are optionaly filtered by "ability to compress" a
- // specifed format.
- //
- // the dialog allows the user to configure or bring up the compressors
- // about box.
- //
- // the selected compressor is opened (via ICOpen) and returned to the
- // caller, it must be disposed of with ICClose() when no longer in use.
- //
- // input:
- // HWND hwnd parent window for dialog box.
- // DWORD fccType compressor types to display. use ICTYPE_VIDEO for video compressors.
- // UINT uiFlags flags, unused must be 0
- // LPVOID pvIn input format (optional), only compressors that handle this format will be displayed.
- // LPVOID lpData input data (optional, currently not used) is specifed this data will be used as a compress preview.
- // HIC FAR *phic return HIC (caller must call ICClose when done)
- // LONG FAR *plQuality return quality
- //
- // returns:
- // TRUE if dialog shown and user choosed a compressor.
- // FALSE if dialog was not shown or user hit cancel.
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- BOOL FAR ICChooseCompressor(
- HWND hwnd, // parent window for dialog
- DWORD fccType, // compressor type to choose
- UINT uiFlags, // flags.
- LPVOID pvIn, // input format (optional)
- LPVOID lpData, // input data (optional)
- HIC FAR *phic, // return HIC (caller must free)
- LONG FAR *plQuality) // return quality
- {
- BOOL f;
- PICChooseCompressorStuff p;
-
- if (fccType == 0)
- fccType = ICTYPE_VIDEO;
-
- p = (LPVOID)GlobalAllocPtr(GHND, sizeof(ICChooseCompressorStuff));
-
- if (p == NULL)
- return FALSE;
-
- p->fccType = fccType;
- p->uiFlags = uiFlags;
- p->pvIn = pvIn;
- p->lQuality = plQuality ? *plQuality : ICQUALITY_DEFAULT;
-
- f = DialogBoxParam(GetWindowInstance(hwnd),
- "ICChooseCompressor", hwnd, ICChooseCompressorDlgProc, (LPARAM)(LPVOID)p);
-
- //
- // if the user picked a compressor then return this info to the caller
- //
- if (f)
- {
- if (plQuality)
- *plQuality = p->lQuality;
-
- if (phic)
- *phic = p->hic;
- else if (p->hic)
- ICClose(p->hic);
- }
-
- GlobalFreePtr(p);
-
- return f;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // ICChooseCompressorDlgProc
- //
- // dialog box procedure for ICChooseCompressor, a pointer to a
- // ICChooseCompressorStuff pointer must be passed to initialize this
- // dialog.
- //
- // NOTE: this dialog box procedure does not use any globals
- // so I did not bother to _export it or use MakeProcAddress() if
- // you change this code to use globals, etc, be aware of this fact.
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- static BOOL CALLBACK ICChooseCompressorDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- int i,n;
- int pos;
- HWND hwndC;
- PICChooseCompressorStuff p;
- HIC hic;
- BOOL fConfig, fAbout, fQuality;
-
- p = (PICChooseCompressorStuff)GetWindowLong(hwnd,DWL_USER);
-
- switch (msg)
- {
- case WM_INITDIALOG:
- if (lParam == NULL)
- return FALSE;
-
- SetWindowLong(hwnd,DWL_USER,lParam);
- p = (PICChooseCompressorStuff)lParam;
-
- //
- // now fill the combo box with all compressors
- //
- hwndC = GetDlgItem(hwnd, ID_COMPRESSOR);
-
- for (i=0; ICInfo(p->fccType, i, &p->icinfo); i++)
- {
- hic = ICOpen(p->icinfo.fccType, p->icinfo.fccHandler, ICMODE_QUERY);
-
- if (hic)
- {
- //
- // skip this compressor if it can't handle the
- // specifed format
- //
- if (p->fccType == ICTYPE_VIDEO &&
- p->pvIn != NULL &&
- ICCompressQuery(hic, p->pvIn, NULL) != ICERR_OK &&
- ICDecompressQuery(hic, p->pvIn, NULL) != ICERR_OK)
- {
- ICClose(hic);
- continue;
- }
-
- //
- // find out the compressor name.
- //
- ICGetInfo(hic, &p->icinfo, sizeof(p->icinfo));
-
- //
- // stuff it into the combo box
- //
- n = ComboBox_AddString(hwndC,p->icinfo.szDescription);
- ComboBox_SetItemData(hwndC, n, hic);
- }
- }
-
- SetScrollRange(GetDlgItem(hwnd, ID_QUALITY),SB_CTL,0,100,TRUE);
- ComboBox_SetCurSel(hwndC, 0);
- PostMessage(hwnd, WM_COMMAND, ID_COMPRESSOR, MAKELONG(hwndC, CBN_SELCHANGE));
- return TRUE;
-
- case WM_HSCROLL:
- pos = GetScrollPos((HWND)HIWORD(lParam),SB_CTL);
-
- switch (wParam)
- {
- case SB_LINEDOWN: pos += 1; break;
- case SB_LINEUP: pos -= 1; break;
- case SB_PAGEDOWN: pos += 10; break;
- case SB_PAGEUP: pos -= 10; break;
- case SB_THUMBTRACK:
- case SB_THUMBPOSITION: pos = LOWORD(lParam); break;
- default:
- return TRUE;
- }
-
- if (pos < 0)
- pos = 0;
- if (pos > (ICQUALITY_HIGH/100))
- pos = (ICQUALITY_HIGH/100);
-
- SetDlgItemInt(hwnd, ID_QUALITYTEXT, pos, FALSE);
- SetScrollPos((HWND)HIWORD(lParam), SB_CTL, pos, TRUE);
- break;
-
- case WM_COMMAND:
- hwndC = GetDlgItem(hwnd, ID_COMPRESSOR);
- n = ComboBox_GetCurSel(hwndC);
- hic = n == -1 ? NULL : (HIC)ComboBox_GetItemData(hwndC,n);
-
- switch ((int)wParam)
- {
- case ID_COMPRESSOR:
- if (HIWORD(lParam) != CBN_SELCHANGE)
- break;
-
- if (hic)
- {
- ICGetInfo(hic, &p->icinfo, sizeof(p->icinfo));
-
- fConfig = ICQueryConfigure(hic);
- fAbout = ICQueryAbout(hic);
- fQuality = (p->icinfo.dwFlags & VIDCF_QUALITY) != 0;
-
- EnableWindow(GetDlgItem(hwnd, ID_CONFIG), fConfig);
- EnableWindow(GetDlgItem(hwnd, ID_ABOUT), fAbout);
- EnableWindow(GetDlgItem(hwnd, ID_QUALITY), fQuality);
- EnableWindow(GetDlgItem(hwnd, ID_QUALITYLABEL), fQuality);
-
- if (fQuality)
- {
- if (p->lQuality == ICQUALITY_DEFAULT)
- {
- SetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL,
- (int)ICGetDefaultQuality(hic)/100, TRUE);
- }
- else
- {
- SetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL,
- (int)p->lQuality/100, TRUE);
- }
-
- pos = GetScrollPos(GetDlgItem(hwnd, ID_QUALITY),SB_CTL);
- SetDlgItemInt(hwnd, ID_QUALITYTEXT, pos, FALSE);
- }
- }
- break;
-
- case ID_CONFIG:
- if (hic)
- ICConfigure(hic, hwnd);
- break;
-
- case ID_ABOUT:
- if (hic)
- ICAbout(hic, hwnd);
- break;
-
- case IDOK:
- ComboBox_SetItemData(hwndC,n,0);
-
- p->hic = hic;
- p->lQuality = 100 * GetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL);
-
- // fall though
-
- case IDCANCEL:
- n = ComboBox_GetCount(hwndC);
- for (i=0; i<n; i++)
- {
- if (hic = (HIC)ComboBox_GetItemData(hwndC,i))
- ICClose(hic);
- }
- EndDialog(hwnd, wParam == IDOK);
- break;
- }
- break;
- }
-
- return FALSE;
- }
-