Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Формат jpg и bmp


Автор: nikakoi 16.6.2006, 09:55
Очень хочу понять как устроены jpg и bmp файлы... можно ли каким то образом считывать их попиксельно и выводить на экран не файл целиком, а какое то количество пикселей??
Вообще есть какие-нить книжки на эту тему??? 

Автор: Nuzur 16.6.2006, 10:20
BMP точно можно и без особых напрягов, с jpg нужно будет повозиться.
А вообще вопрос не совсем ясен, что тебя интересует сама структура файлов? Как с ними работать? По привязке к MFC или где? Уточни. 

Автор: nikakoi 16.6.2006, 10:24
Млин...Почему то все мои вопросы не совсем ясныsmile (чувствую себя довольно неуютноsmile)
Меня интересует структура файлов(особенно jpg.. с bmp просто для общего развития хочу разобраться)...
И как с ними работать в MFC, а точнее как мне работать с их пикселамиsmile...   

Автор: Rapalex 16.6.2006, 10:37
Поповоду jpg из слов других людей скажу, что там берётся изображение разбивается на квадратики по 8х8 пикселей, после чего цвета квадрата какимто образом преобразуется в ряд Фурье (чем качествене сжатие тем длинее ряд) и полученые коэфиценты сохраняются в файл, И ПОСЛЕ этого этот файл сжимается LZ алгоритмом (когда наиболее чясто встречающиеся символь заменяются меньшим количеством бит, как в zip или rar), и вод этот файл и есть файл jpg.

А в VC есть такой класс CImage, если им пользоваться то экзешник начинает требовать GDIplus.dll, покрайне мере так было VC 7.0/7.1 (2002/2003).

CImage provides enhanced bitmap support, including the ability to load and save images in JPEG, GIF, BMP, and Portable Network Graphics (PNG) formats. 

С ним можнао работать почти как с обычным bmp. 

Автор: nikakoi 16.6.2006, 12:41
Я в MSDN поискал уже про этот CImage...
Я пишу на VC6 и тут кажется такого класса нетsmile 

Автор: SeregaLBN 16.6.2006, 15:58
Вот пример простого класса CImage и его использования. Нужно только в примере подставить путь к своей картинке.
Класс CImage - обёртка над стандартным COM интерфейсом IPicture.
Т.е. я отвечаю только за загрузку файла, и всё!
За рисование его отвечает сама система. И об типе файла задумаваться не нужно.
Пробовал на bmp, ico, gif, jpeg, emf, wmf. Отображает.
Код

#define WIN32_LEAN_AND_MEAN        // Exclude rarely-used stuff from Windows headers

#include <windows.h>
#include <tchar.h>
#include <ocidl.h>
#include <olectl.h>

#define HIMETRIC_INCH   2540

class CImage {
private:
   IPicture  *m_pPicture;
private:
   BOOL Release();
public:
   CImage(LPCTSTR szFileName = NULL);
  ~CImage() { Release(); }
   SIZE GetSizeImage() const;

   BOOL Draw(HDC hDC, const RECT&) const;
   BOOL Load(LPCTSTR szFileName);
};


////////////////////////////////////////////////////////////////////////////////
//                            other function
////////////////////////////////////////////////////////////////////////////////

SIZE PictureSize(IPicture *pPicture, bool bPixel) {
   SIZE size = {0,0};
   DWORD dwErrCode = NO_ERROR;
   if (!pPicture) {
      dwErrCode = ERROR_INVALID_PARAMETER;
   } else {
      OLE_YSIZE_HIMETRIC hmHeight = 0;
      HRESULT hRes = pPicture->get_Height(&hmHeight);
      if (FAILED(hRes)) {
         dwErrCode = HRESULT_CODE(hRes);
      } else {
         OLE_XSIZE_HIMETRIC hmWidth = 0;
         hRes = pPicture->get_Width(&hmWidth);
         if (FAILED(hRes)) {
            dwErrCode = HRESULT_CODE(hRes);
         } else {
            if (bPixel) {
               HDC hDC = ::GetDC(::GetDesktopWindow());
               size.cx = MulDiv(hmWidth , ::GetDeviceCaps(hDC, LOGPIXELSX), HIMETRIC_INCH);
               size.cy = MulDiv(hmHeight, ::GetDeviceCaps(hDC, LOGPIXELSY), HIMETRIC_INCH);
               ::ReleaseDC(::GetDesktopWindow(), hDC);
            } else {
               size.cx = hmWidth;
               size.cy = hmHeight;
            }
         }
      }
   }
   ::SetLastError(dwErrCode);
   return size;
}

HRESULT LoadPictFromFile(IN OUT IPicture **ppPicture, IN LPCTSTR szFile) {
   HRESULT hRes = S_OK;
   DWORD dwErrCode = NO_ERROR;
   if (!ppPicture || !szFile || !szFile[0]) {
      hRes = HRESULT_FROM_WIN32(dwErrCode = ERROR_INVALID_PARAMETER);
   } else {
      *ppPicture = NULL;
   }

   HANDLE hFile = INVALID_HANDLE_VALUE;
   DWORD dwFileSize = 0;
   if (SUCCEEDED(hRes)) {
      hFile = ::CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
      if (hFile == INVALID_HANDLE_VALUE) {
         hRes = HRESULT_FROM_WIN32(dwErrCode = ::GetLastError());
      } else {
         dwFileSize = ::GetFileSize(hFile, NULL);
         if (dwFileSize == 0xFFFFFFFF) {
            hRes = HRESULT_FROM_WIN32(dwErrCode = ::GetLastError());
         }
      }
   }

   HGLOBAL hGlobal = NULL;
   LPVOID pData = NULL;
   if (SUCCEEDED(hRes)) {
      // alloc memory based on file size
      hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
      if (!hGlobal) {
         hRes = HRESULT_FROM_WIN32(dwErrCode = ::GetLastError());
      } else {
         pData = ::GlobalLock(hGlobal);
         if (!pData) {
            hRes = HRESULT_FROM_WIN32(dwErrCode = ::GetLastError());
         }
      }
   }

   DWORD dwNBOR = 0;
   if (SUCCEEDED(hRes)) {
      // read file and store in global memory
      if (!::ReadFile(hFile, pData, dwFileSize, &dwNBOR, NULL) || (dwFileSize!=dwNBOR)) {
         hRes = HRESULT_FROM_WIN32(dwErrCode = ::GetLastError());
      }
   }
   
   LPSTREAM pStm = NULL;
   if (SUCCEEDED(hRes)) {
      if (SUCCEEDED(hRes)) {
         // create IStream* from global memory
         hRes = ::CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);
         if (SUCCEEDED(hRes) && !pStm) {
            hRes = E_FAIL;
         }
      }

      if (SUCCEEDED(hRes)) {
         // Create IPicture from image file
         hRes = ::OleLoadPicture(pStm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)ppPicture);
         if (SUCCEEDED(hRes) && (*ppPicture == NULL)) {
            hRes = E_FAIL;
         }
      }

   }

   // free data
   if (pStm) {
      pStm->Release(); pStm = NULL;
   }
   if (hGlobal) {
      ::GlobalUnlock(hGlobal);
      ::GlobalFree(hGlobal);
   }
   if (hFile != INVALID_HANDLE_VALUE) {
      ::CloseHandle(hFile);
   }

   ::SetLastError(FAILED(hRes) ? dwErrCode ? dwErrCode : HRESULT_CODE(hRes) : dwErrCode);

   return hRes;
}

////////////////////////////////////////////////////////////////////////////////
//                         implementation CImage
////////////////////////////////////////////////////////////////////////////////

CImage::CImage(LPCTSTR szFileName) : m_pPicture (NULL)
{
   if (szFileName) {
      Load(szFileName);
   }
}


BOOL CImage::Load(LPCTSTR szFileName) {
   BOOL bRes = TRUE;
   DWORD dwErrCode = NO_ERROR;
   if (!szFileName || !szFileName[0]) {
      dwErrCode = ERROR_INVALID_PARAMETER;
      bRes = FALSE;
   } else {
      HANDLE hImageNew = NULL;
      IPicture *pPicture = NULL;
      bRes = SUCCEEDED(::LoadPictFromFile(&pPicture, szFileName));
      if (!bRes) {
         dwErrCode = ::GetLastError();
      } else {
         Release();
         m_pPicture = pPicture;
      }
   }
   ::SetLastError(dwErrCode);
   return bRes;
}

BOOL CImage::Release() {
   BOOL bRes = !!m_pPicture;
   if (m_pPicture) {
      m_pPicture->Release();
      m_pPicture = NULL;
   }
   return bRes;
}

SIZE CImage::GetSizeImage() const {
   return PictureSize(m_pPicture, true);
}

BOOL CImage::Draw(HDC hDC, const RECT &rect) const {
   BOOL bRes = TRUE;
   DWORD dwErrCode = NO_ERROR;
   if (m_pPicture) {
      //SIZE sizeP = PictureSize(m_pPicture, true);
      SIZE sizeH = PictureSize(m_pPicture, false);
    //HRESULT hRes = m_pPicture->Render(hDC, 0, 0, sizeP.cx, sizeP.cy, 0, sizeH.cy, sizeH.cx, -sizeH.cy, &rect);
      HRESULT hRes = m_pPicture->Render(hDC, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, sizeH.cy, sizeH.cx, -sizeH.cy, &rect);
      if (FAILED(hRes)) {
         dwErrCode = HRESULT_CODE(hRes);
      }
   }
   ::SetLastError(dwErrCode);
   return bRes;
}

////////////////////////////////////////////////////////////////////////////////
//                            main part
////////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
   WNDCLASSEX wcex = {
      sizeof(WNDCLASSEX),              // UINT        cbSize;
      CS_HREDRAW | CS_VREDRAW,         // UINT        style;
      (WNDPROC)WndProc,                // WNDPROC     lpfnWndProc;
      0,                               // int         cbClsExtra;
      0,                               // int         cbWndExtra;
      hInstance,                       // HINSTANCE   hInstance;
      NULL,                            // HICON       hIcon;
      LoadCursor(NULL, IDC_ARROW),     // HCURSOR     hCursor;
      GetSysColorBrush(COLOR_BTNFACE), // HBRUSH      hbrBackground;
      NULL,                            // LPCSTR      lpszMenuName;
      _T("TestImageWindowClass"),      // LPCSTR      lpszClassName;
      NULL                             // HICON       hIconSm;
   };
    RegisterClassEx(&wcex);
   
   HWND hWnd = CreateWindow(_T("TestImageWindowClass"), _T("Test CImage"), WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);


   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0))  {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
   switch (message) {
   case WM_PAINT:
      {
         PAINTSTRUCT ps;
         HDC hdc = BeginPaint(hWnd, &ps);
         RECT rt; GetClientRect(hWnd, &rt);
         static CImage img(_T("c:\\img\\index_r1_c3.jpg"));
         img.Draw(hdc, rt);
         EndPaint(hWnd, &ps);
      }
      break;
   case WM_DESTROY:
      PostQuitMessage(0);
      break;
   default:
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}
 

Автор: Rapalex 17.6.2006, 10:51
Может быть, хотя я сомневаюсь, просто я начинл с VS 7.0 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)