]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dib.cpp
new wxDIB class
[wxWidgets.git] / src / msw / dib.cpp
index a62948302212ef72720a89b97c62d1d51e7d1363..632e70c5524f7edd4a520838da00a8d2d46a262b 100644 (file)
@@ -1,3 +1,190 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/msw/dib.cpp
+// Purpose:     implements wxDIB class
+// Author:      Vadim Zeitlin
+// Modified by:
+// Created:     03.03.03 (replaces the old file with the same name)
+// RCS-ID:      $Id$
+// Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
+// License:     wxWindows license
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/log.h"
+#endif //WX_PRECOMP
+
+#include "wx/image.h"
+
+#include "wx/msw/dib.h"
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxDIB creation
+// ----------------------------------------------------------------------------
+
+bool wxDIB::Create(int width, int height, int depth)
+{
+    // we don't handle the palette yet
+    wxASSERT_MSG( depth == 24 || depth == 32,
+                    _T("unsupported image depth in wxDIB::Create()") );
+
+    static const int infosize = sizeof(BITMAPINFOHEADER);
+
+    BITMAPINFO *info = (BITMAPINFO *)malloc(infosize);
+    wxCHECK_MSG( info, NULL, _T("malloc(BITMAPINFO) failed") );
+
+    memset(info, 0, infosize);
+
+    info->bmiHeader.biSize = infosize;
+    info->bmiHeader.biWidth = width;
+    info->bmiHeader.biHeight = -height;
+    info->bmiHeader.biPlanes = 1;
+    info->bmiHeader.biBitCount = depth;
+    info->bmiHeader.biCompression = BI_RGB;
+    info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
+
+    // No need to report an error here.  If it fails, we just won't use a
+    // file mapping and CreateDIBSection will just allocate memory for us.
+    m_handle = ::CreateDIBSection
+                 (
+                    0,              // hdc (unused with DIB_RGB_COLORS)
+                    info,           // bitmap description
+                    DIB_RGB_COLORS, // use RGB, not palette
+                    &m_data,        // [out] DIB bits
+                    NULL,           // don't use file mapping
+                    0               // file mapping offset (not used here)
+                 );
+
+    free(info);
+
+    if ( !m_handle )
+    {
+        wxLogLastError(wxT("CreateDIBSection"));
+
+        return false;
+    }
+
+    m_width = width;
+    m_height = height;
+    m_depth = depth;
+
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+// wxDIB accessors
+// ----------------------------------------------------------------------------
+
+void wxDIB::DoGetObject() const
+{
+    // only do something if we have a valid DIB but we don't [yet] have valid
+    // data
+    if ( m_handle && !m_data )
+    {
+        // although all the info we need is in BITMAP and so we don't really
+        // need DIBSECTION we still ask for it as modifying the bit values only
+        // works for the real DIBs and not for the bitmaps and it's better to
+        // check for this now rather than trying to find out why it doesn't
+        // work later
+        DIBSECTION ds;
+        if ( !::GetObject(m_handle, sizeof(ds), &ds) )
+        {
+            wxLogLastError(_T("GetObject(hDIB)"));
+
+            return;
+        }
+
+        wxDIB *self = wxConstCast(this, wxDIB);
+
+        self->m_width = ds.dsBm.bmWidth;
+        self->m_height = ds.dsBm.bmHeight;
+        self->m_depth = ds.dsBm.bmBitsPixel;
+        self->m_data = ds.dsBm.bmBits;
+    }
+}
+
+// ----------------------------------------------------------------------------
+// wxImage support
+// ----------------------------------------------------------------------------
+
+#if wxUSE_IMAGE
+
+bool wxDIB::Create(const wxImage& image)
+{
+    wxCHECK_MSG( image.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
+
+    const int h = image.GetHeight();
+    const int w = image.GetWidth();
+
+    // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
+    // a 24bpp RGB is sufficient
+    const bool hasAlpha = image.HasAlpha();
+    const int bpp = hasAlpha ? 32 : 24;
+
+    if ( !Create(w, h, bpp) )
+        return false;
+
+    // DIBs are stored in bottom to top order so we need to copy bits line by
+    // line and starting from the end
+    const int srcBytesPerLine = w * 3;
+    const int dstBytesPerLine = GetLineSize(w, bpp);
+    const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
+    const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
+    unsigned char *dstLineStart = (unsigned char *)m_data;
+    for ( int y = 0; y < h; y++ )
+    {
+        // copy one DIB line
+        unsigned char *dst = dstLineStart;
+        for ( int x = 0; x < w; x++ )
+        {
+            // also, the order of RGB is inversed for DIBs
+            *dst++ = src[2];
+            *dst++ = src[1];
+            *dst++ = src[0];
+
+            src += 3;
+
+            if ( alpha )
+                *dst++ = *alpha++;
+        }
+
+        // pass to the previous line in the image
+        src -= 2*srcBytesPerLine;
+        if ( alpha )
+            alpha -= 2*w;
+
+        // and to the next one in the DIB
+        dstLineStart += dstBytesPerLine;
+    }
+
+    return true;
+}
+
+#endif // wxUSE_IMAGE
+
+// ============================================================================
+// old DIB code, to be integrated in wxDIB class
+// ============================================================================
+
 /*******************************************************************************
  *                                                                               *
  * MODULE        : DIB.CC                                                        *
 #endif
 
 #ifndef WX_PRECOMP
-#include "wx/setup.h"
-#include "wx/defs.h"
 #include "wx/bitmap.h"
+#include "wx/log.h"
+#include "wx/intl.h"
 #endif
 
 #include <windows.h>
 
 #include "wx/msw/dib.h"
 
-#ifndef __TWIN32__
-#ifndef wxUSE_NORLANDER_HEADERS
-#ifdef __GNUWIN32__
-#include "wx/msw/gnuwin32/extra.h"
-#endif
-#endif
+#ifdef __GNUWIN32_OLD__
+    #include "wx/msw/gnuwin32/extra.h"
 #endif
 
 #ifndef SEEK_CUR
@@ -113,7 +296,7 @@ static BOOL WriteDIB(LPTSTR szFile, HANDLE hdib)
         if (!hdib)
                 return FALSE;
 
-        fh = OpenFile(wxFNCONV(szFile), &of, OF_CREATE | OF_READWRITE);
+        fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE);
         if (fh == -1)
                 return FALSE;
 
@@ -163,9 +346,9 @@ WORD wxPaletteSize(VOID FAR * pv)
         NumColors = DibNumColors(lpbi);
 
         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
-                return NumColors * sizeof(RGBTRIPLE);
+                return (WORD)(NumColors * sizeof(RGBTRIPLE));
         else
-                return NumColors * sizeof(RGBQUAD);
+                return (WORD)(NumColors * sizeof(RGBQUAD));
 }
 
 /****************************************************************************
@@ -357,7 +540,7 @@ static HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hp
 static DWORD PASCAL lread(int fh, void far *pv, DWORD ul)
 {
         DWORD     ulT = ul;
-#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) || defined(__WXWINE__)
+#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
         BYTE *hp = (BYTE *) pv;
 #else
         BYTE huge *hp = (BYTE huge *) pv;
@@ -368,7 +551,7 @@ static DWORD PASCAL lread(int fh, void far *pv, DWORD ul)
                 ul -= MAXREAD;
                 hp += MAXREAD;
                 }
-        if (_lread(fh, (LPSTR) hp, (WORD) ul) != (WORD) ul)
+        if (_lread(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
                 return 0;
         return ulT;
 }
@@ -387,7 +570,7 @@ static DWORD PASCAL lread(int fh, void far *pv, DWORD ul)
 static DWORD PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
 {
         DWORD     ulT = ul;
-#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) || defined(__WXWINE__)
+#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
         BYTE *hp = (BYTE *) pv;
 #else
         BYTE huge *hp = (BYTE huge *) pv;
@@ -398,7 +581,7 @@ static DWORD PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
                 ul -= MAXREAD;
                 hp += MAXREAD;
                 }
-        if (_lwrite(fh, (LPSTR) hp, (WORD) ul) != (WORD) ul)
+        if (_lwrite(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
                 return 0;
         return ulT;
 }
@@ -433,7 +616,7 @@ BOOL wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette)
 
     /* Open the file and get a handle to it's BITMAPINFO */
 
-    fh = OpenFile (wxFNCONV(lpFileName), &of, OF_READ);
+    fh = OpenFile (wxConvertWX2MB(lpFileName), &of, OF_READ);
     if (fh == -1) {
         wxLogError(_("Can't open file '%s'"), lpFileName);
         return (0);
@@ -532,7 +715,7 @@ BOOL wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette)
     }
 
     /* offset to the bits from start of DIB header */
-    offBits = (WORD)lpbi->biSize + nNumColors * sizeof(RGBQUAD);
+    offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD));
 
     if (bf.bfOffBits != 0L)
     {
@@ -623,6 +806,9 @@ static BOOL PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
             result = TRUE;
         }
     }
+
+       GlobalUnlock (hDIB);  // glt
+
     return(result);
 }
 
@@ -640,9 +826,6 @@ static BOOL PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
  ****************************************************************************/
 HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
 {
-#ifdef __WXWINE__
-        return (FALSE);
-#else
     LPLOGPALETTE npPal;
     RGBQUAD far *lpRGB;
     HPALETTE hLogPal;
@@ -660,7 +843,7 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
         npPal = (LPLOGPALETTE)malloc(sizeof(LOGPALETTE) +
                                 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
         if (!npPal)
-            return(FALSE);
+            return NULL;
 
         npPal->palVersion = 0x300;
         npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
@@ -669,7 +852,7 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
         lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
 
         /* copy colors from the color table to the LogPalette structure */
-        for (i = 0; i < lpInfo->biClrUsed; i++, lpRGB++)
+        for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++)
         {
             npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
             npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
@@ -690,31 +873,32 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
     */
     else
         return((HPALETTE) GetStockObject(DEFAULT_PALETTE));
-#endif
-
 }
 
 bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal)
 {
-  HBITMAP hBitmap;
-  HPALETTE hPalette;
+  HBITMAP hBitmap = NULL;
+  HPALETTE hPalette = NULL;
 
   bool success = (wxReadDIB(filename, &hBitmap, &hPalette) != 0);
 
   if (!success)
   {
-    DeleteObject(hPalette);
+    if (hPalette)
+        DeleteObject(hPalette);
     return FALSE;
   }
 
   if (hPalette)
   {
+#if wxUSE_PALETTE
     if (pal)
     {
       *pal = new wxPalette;
       (*pal)->SetHPALETTE((WXHPALETTE) hPalette);
     }
     else
+#endif // wxUSE_PALETTE
       DeleteObject(hPalette);
   }
   else if (pal)
@@ -929,8 +1113,10 @@ HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal)
 bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *colourmap)
 {
   HPALETTE hPalette = 0;
+#if wxUSE_PALETTE
   if (colourmap)
     hPalette = (HPALETTE) colourmap->GetHPALETTE();
+#endif // wxUSE_PALETTE
 
   HANDLE dibHandle = wxBitmapToDIB((HBITMAP) bitmap->GetHBITMAP(), hPalette);
   if (dibHandle)
@@ -942,4 +1128,3 @@ bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *colourmap)
   else return FALSE;
 }
 
-