WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  C / C++ / Visual C++
  Работа с графическими файлами

СПРОСИТЬ  ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Работа с графическими файлами
xKernel опубликован 14-01-2002 08:37 MSK   Click Here to See the Profile for xKernel   Click Here to Email xKernel  
Кто нибудь знает какую нибудь библиотеку для работы с графическими файлами разных форматов (JPG, GIF ...)?
ADK опубликован 15-01-2002 06:28 MSK     Click Here to See the Profile for ADK  Click Here to Email ADK     
Сегодня практически все программы используют различные картинки в качестве элементов интерфейса. Даже существует API функция ::LoadImage(), умеющая загружать файлы в формате bmp, ico и cur. Этого достаточно для панелей управления и диалогов. Но если размер картинки превышает 100x100 пикселов и их нужно несколько, файлы формата bmp использовать не удобно. Хочется что-то вроде jpg или gif.
Тут ::LoadImage() нам уже не помошник. Придется использовать специальные библиотеки. Наибольшей популярностью пользуются:
Independent JPEG Group
Portable Network Graphics
TIFF Software
Intel(R) JPEG Library
Image Library
CXImage
Small JPEG Decoder Library
Все они хорошо документированны и снабжены примерами. Подробное рассмотрение этих библиотек займет слишком много времени и выходит за рамки этой статьи. Давайте лучше уделим внимание некоторым специальным API, предназначенным для работы с файлами изображений.
Способ 1 (OleLoadPicture)
Самый "официальный" способ. Появился вместе с OLE32 и работает до сих пор. Функции OleLoadPicture(Ex) и OleLoadPicturePath умеют загружать картинки в формате BMP, GIF, JPEG, ICO, WMF, и EMF:

#include <olectl.h>

HRESULT Load(LPCTSTR szFile)
{
CComPtr<IStream> pStream;

// Load the file to a memory stream
HRESULT hr = FileToStream(szFile, &pStream);

if (SUCCEEDED(hr))
{
// Decode the picture
hr = ::OleLoadPicture(
pStream, // [in] Pointer to the stream that contains picture's data
0, // [in] Number of bytes read from the stream (0 == entire)
true, // [in] Loose original format if true
IID_IPicture, // [in] Requested interface
(void**)&m_pPicture // [out] IPictire object on success
);
}

return hr;
}

HRESULT DrawImg(HDC hdc, const RECT& rcBounds)
{
if (m_pPicture)
{
// Get the width and the height of the picture
long hmWidth = 0, hmHeight = 0;
m_pPicture->get_Width(&hmWidth);
m_pPicture->get_Height(&hmHeight);

// Convert himetric to pixels
int nWidth = MulDiv(hmWidth, ::GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
int nHeight = MulDiv(hmHeight, ::GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);

// Display the picture using IPicture::Render
return m_pPicture->Render(
hdc, // [in] Handle of device context on which to render the image
rcBounds.left, // [in] Horizontal position of image in hdc
rcBounds.top, // [in] Vertical position of image in hdc
rcBounds.right - rcBounds.left, // [in] Horizontal dimension of destination rect.
rcBounds.bottom - rcBounds.top, // [in] Vertical dimension of destination rect.
0, // [in] Horizontal offset in source picture
hmHeight, // [in] Vertical offset in source picture
hmWidth, // [in] Amount to copy horizontally in source picture
-hmHeight, // [in] Amount to copy vertically in source picture
&rcBounds // [in, optional] Pointer to position of destination for a metafile hdc
);
}

return E_UNEXPECTED;
}
Достоинства: правильно работает с прозрачными картинками.
Недостатки: не поддерживает анимированный GIF (см. также CPicturEx). Не поддерживает PNG.
Способ 2 (GDI+)
Недостаток ::LoadImage() с лихвой исправили в GDI+. Объект Gdiplus::Image умеет загружать картинки в формате BMP, GIF, JPEG, PNG, TIFF, EXIF, WMF, и EMF:

#include <gdiplus.h>

HRESULT Load(LPCTSTR szFile)
{
USES_CONVERSION;
// Create new Gdiplus::Image object
m_pImage = new Gdiplus::Image(T2CW(szFile));
ATLASSERT(m_pImage);

// Check for success
if (Gdiplus::Ok == m_pImage->GetLastStatus())
return S_OK;

// Cleanup on failure
Destroy();
return E_FAIL;
}

HRESULT DrawImg(HDC hdc, RECT& rcBounds)
{
if (m_pImage)
{
// Create Gdiplus::Graphics object from HDC
Gdiplus::Graphics graphics(hdc);
// Create Gdiplus::Rect object from RECT
Gdiplus::Rect rc(rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom);

// Draw the image
return Gdiplus::Ok == graphics.DrawImage(
m_pImage, // [in] Gdiplus::Image object
rc // [in] Position and dimensions
) ? S_OK : E_FAIL;
}

return E_UNEXPECTED;
}
Достоинства: понимает множество форматов, в том числе анимированный GIF, правильно работает с прозрачными картинками.
Недостатки: На сегодняшний момент реализован только в WindowsXP. Хотя простое копирование gdiplus.dll в system32 делает ее доступной, как минимум, в Windows2000. Скорее всего, в обозримом будущем ожидаются версии и для Win9x.
Способ 3 (IImgCtx)
Не так давно Майкрософт предоставила заголовочные и библиотечные файлы к объекту ImgCtx, появившемуся еще в Internet Explorer 4.0. Он умеет заргужать картинки в формате BMP, GIF, JPEG, ICO, WMF, EMF, PNG, XBM, ICO, TIFF и, возможно, некоторых других:

#include <IImgCtx.h>

HRESULT Load(LPCTSTR szFile)
{
// Create IImgCtx object
HRESULT hr = ::CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_ALL, IID_IImgCtx, (void**)&m_pImage);
if (SUCCEEDED(hr))
{
// Load URL
USES_CONVERSION;
hr = m_pImage->Load(
T2COLE(szFile), // [in] URL
0 // [in] Flags and preffered color format
);
}

return hr;
}

HRESULT DrawImg(HDC hdc, RECT& rcBounds)
{
if (m_pImage)
{
// Check download state
DWORD dwState = 0;
HRESULT hr = m_pImage->GetStateInfo(&dwState, NULL, true);
if (SUCCEEDED(hr))
{
if (IMGLOAD_LOADING & dwState)
{
// Still loading - wait 50 msec and request again
::DrawText(hdc, _T("Loading, please wait..."), -1, &rcBounds, DT_SINGLELINE);
::Sleep(50);
Invalidate(false);

hr = S_FALSE;
}
else if (IMGLOAD_COMPLETE & dwState)
{
// Download successfully complete
hr = m_pImage->Draw(
hdc, // [in] Handle of device context on which to render the image
&rcBounds // [in] Position and dimensions
);
}
else
{
// Download failed
hr = E_UNEXPECTED;
}
}
return hr;
}

return E_UNEXPECTED;
}
Достоинства: правильно работает с прозрачными и анимированными картинками. Понимает URL (даже res:// и sysimage://).
Недостатки: не поддерживает загрузку из IStream. Не умеет загружать файлы синхронно.
ПРИМЕЧАНИЕ
Форматов, распознаваемых этим объектом, может быть меньше, например, если при установке IE4 позьзователь отключил поддержку PNG файлов.
Способ 4 (DirectXTransform)
Не смотря на название, эта технология не имеет ничего общего с DirectX. Зато является частью Internet Explorer, внутри которого даже имется набор простеньких классов, реализующих IDirectDraw для нужд DirectXTransform. Этот способ поддерживает тот же набор форматов, что и предыдущий, более того, для этого используется один и тот же код. Разве что синхронно и на выходе получается IDXSurface объект.

#include <dxtrans.h>

HRESULT DrawImg(HDC hdc, const RECT& rcBounds)
{
if (m_pDCLock)
{
HDC hdcImage = m_pDCLock->GetDC();

// Get the bitmap
HGDIOBJ hObj = ::GetCurrentObject(hdcImage, OBJ_BITMAP);
BITMAP bm = {0};

// Get the size of the bitmap
if (hObj && ::GetObject(hObj, sizeof(BITMAP), &bm))
{
// Draw the image
return ::StretchBlt(
hdc,
rcBounds.left, rcBounds.top,
rcBounds.right - rcBounds.left,
rcBounds.bottom - rcBounds.top,
hdcImage,
0, 0,
bm.bmWidth, bm.bmHeight,
SRCCOPY
) ? S_OK : E_FAIL;
}
}

return E_UNEXPECTED;
}

HRESULT Load(LPCTSTR szFile)
{
CComPtr<IDXTransformFactory> pTransFact;
CComPtr<IDXSurfaceFactory> pSurfFact;

// Create the Transform Factory.
HRESULT hr = ::CoCreateInstance(CLSID_DXTransformFactory, NULL,
CLSCTX_INPROC, IID_IDXTransformFactory, (void **)&pTransFact);

if (SUCCEEDED(hr))
hr = pTransFact->QueryService(SID_SDXSurfaceFactory,
IID_IDXSurfaceFactory, (void **)&pSurfFact);

if (SUCCEEDED(hr))
{
CComBSTR bstrFile(szFile);
CComPtr<IDXSurface> pDXSurf;

// Load DX surface.
hr = pSurfFact->LoadImage(bstrFile, NULL, NULL,
NULL, IID_IDXSurface, (void**)&pDXSurf);

if (SUCCEEDED(hr))
{
// Get IDXDCLock object
hr = pDXSurf->LockSurfaceDC(NULL, INFINITE, DXLOCKF_READ, &m_pDCLock);
}
}
return hr;
}
Достоинства: Прост в использовании. Поддерживает загрузку из IStream.
Недостатки: Медленный и ресурсоемкий. Это связянно с тем, что сначала для картинки создается обертка в виде IDirectDrawSurface, а затем еще одна для IDXSurface, которые нам совершенно не нужны.
Способ 5 (Фильтры импорта)
Многие программы (например PaintBrush или WinWord) при инсталляции кладут в каталог %ProgramFiles%\Common Files\Microsoft Shared\Grphflt некоторое количество файлов, предназначенных для чтения файлов картинок. Способ не документированный и сильно устаревший. Полный список установленных в системе фильтров находится в реестре по адресу SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Import
Я не буду рассматривать этот способ подробно, поскольку он сильно устарел и очень неудобен. Тем не менее, в приложении DrawImg этот способ реализован наравне с другими.
Способ 6 (Снова Фильтры импорта)
Майкрософт Офис, начиная с версии 8.0 (97) использует новый API с теми же фильтрами.

HRESULT Load(LPCTSTR szFile)
{
HMODULE hModule = g_pMapExtToFilter->LoadFilter(szFile);

if (NULL == hModule)
return E_FAIL;

struct NameStruct
{
DWORD dwHead[2];
char szName[MAX_PATH];
DWORD dwTail[2];
};

typedef DWORD (__stdcall *GetFilterInfo_t)
(DWORD dwVersion, DWORD dwReserved, HGLOBAL *phFilterData, DWORD dwReserved2);
typedef DWORD (__stdcall *SetFilterPref_t)
(HGLOBAL hFilterData, LPCSTR szOption, LPCSTR szValue, DWORD dwReserved2, DWORD dwReserved1);
typedef DWORD (__stdcall *ImportGr_t)
(DWORD dwReserved, NameStruct *pFile, ImgInfo *pInfo, HGLOBAL hFilterData);

GetFilterInfo_t pGetFilterInfo = (GetFilterInfo_t)::GetProcAddress(hModule, "GetFilterInfo");
SetFilterPref_t pSetFilterPref = (SetFilterPref_t)::GetProcAddress(hModule, "SetFilterPref");

ImportGr_t pImportGr = (ImportGr_t)::GetProcAddress(hModule, "ImportGr");
if (NULL == pImportGr)
pImportGr = (ImportGr_t)::GetProcAddress(hModule, "ImportGR");

if (pImportGr)
{
NameStruct name = {0};
HGLOBAL hFilterData = NULL;

if (pGetFilterInfo)
{
DWORD dwVer = pGetFilterInfo(2, 0, &hFilterData, 0x00170000);
ATLASSERT(2 == dwVer);

if (2 != dwVer)
{
::FreeLibrary(hModule);
return E_UNEXPECTED;
}
}

// PB 01/26/2001 Turn off dialogs
if (pSetFilterPref)
{
pSetFilterPref(hFilterData, "ShowProgressDialog", "No", 2, 1);
pSetFilterPref(hFilterData, "ShowOptionsDialog", "No", 2, 1);
}

USES_CONVERSION;
::lstrcpynA(name.szName, T2CA(szFile), MAX_PATH);

DWORD dwRet = pImportGr(0, &name, &m_Image, hFilterData);

if (hFilterData)
::GlobalFree(hFilterData);

if (0 != dwRet

ADK опубликован 15-01-2002 06:30 MSK     Click Here to See the Profile for ADK  Click Here to Email ADK     
if (0 != dwRet
ADK опубликован 15-01-2002 06:32 MSK     Click Here to See the Profile for ADK  Click Here to Email ADK     
"Или" не понимает, блин.

if (OBJ_METAFILE != ::GetObjectType(m_Image.hObj))
{
HGLOBAL hObj = (HGLOBAL)m_Image.hObj;
LPBYTE pObj = (LPBYTE)::GlobalLock(hObj);

m_Image.hObj = ::SetMetaFileBitsEx(::GlobalSize(hObj), pObj);

::GlobalUnlock(hObj);
::GlobalFree(hObj);
}

if (NULL == m_Image.hObj)
{
::FreeLibrary(hModule);
return E_FAIL;
}

return S_OK;
}

::FreeLibrary(hModule);
return E_UNEXPECTED;
}

HRESULT DrawImg(HDC hdc, const RECT& rcBounds)
{
if (m_Image.hObj)
{
::SetMapMode(hdc, MM_ANISOTROPIC);
::SetViewportExtEx(hdc,
rcBounds.right - rcBounds.left,
rcBounds.bottom - rcBounds.top,
NULL);
::PlayMetaFile(hdc, m_Image.hObj);

return S_OK;
}

return E_UNEXPECTED;
}
Достоинства: понимает очень редкие форматы. Например wpg или cdr
Недостатки: Нет никакой гарантии, что на компьютере пользователя будет установлен нужный фильтр.
Способ 7 (Direct3D)
Direct3D версии 8.0 и выше умеет загружать картинки в формате BMP, JPEG, PNG:

#include <d3dx8.h>
HRESULT hr = ::D3DXCreateTextureFromFile(m_pD3DDevice, szFile, &ppTexture);
Достоинства: если вы разрабатываете 3D-приложение, то это наиболее удобный способ создания текстур (D3DXCreateTextureFromFile автоматически создает необходимое количество MipMap уровней).
Недостатки: если вы не разрабатываете 3D-приложение, то этот способ крайне неудобен, так как предназначен для работы с 3D объектами. На входе нужен IDirect3DDevice8 объект, а на выходе получаем IDirect3DTexture8, который очень не просто вывести в HDC.

Alexmoon опубликован 16-01-2002 13:59 MSK     Click Here to See the Profile for Alexmoon  Click Here to Email Alexmoon     
www.codeproject.com/bitmap/

www.painlib.de/paintlib/

Stiff опубликован 16-01-2002 18:34 MSK     Click Here to See the Profile for Stiff  Click Here to Email Stiff     
А кстати говоря кто-нибудь знает как из CxImage записать в мета файл МОжет че скинете если не жалко
Flex Ferrum опубликован 16-01-2002 20:00 MSK     Click Here to See the Profile for Flex Ferrum  Click Here to Email Flex Ferrum     
Еще рекомендую такую библи отеку (ActiveX-компонент) - ImgX Library. Правда у нее один недостаток (как и у многих подобных библиотек сейчас) - не работет с GIF файлами (из-за "особенностей" лицензии на использование GIF). А так работет с BMP, JPG, PNG, TIFF, PSD, WMF, EMF, TGA. Умеет читать, писать, делать всяческие преобразования. Вообщем, урезанный вариант фотощопа.

СПРОСИТЬ  ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.