Click here to Skip to main content
15,886,873 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
I'm Creating my project of Image processing with some filters: Laplace & Sobel, so I created an SDI app, "I didn't uploaded my project, because I am using Xtreme ToolkitPro v15.0.1" & you should have it installed too to be able to compile & understand.

I've created a class named: CFilters
class CFilters
{
public:
   CFilters();
   ~CFilters();

   static void Laplace(BITMAP* pBitMap);
   static void Sobel(BITMAP* pBitMap);
}


& When I click the Laplace Filter or the Sobel one from the main menu, I would like an Instance of the currently loaded & shown CBitmap is created & the BITMAP data is passed to the appropriate filter static function CFilters::Laplace(BITMAP* pBitMap); or CFilters::Sobel(BITMAP* pBitMap); so the pBitMap->bmBits will be modified & I can show the filtered Bitmap;

I'm unable to do that!

Help me please;
Posted

In my opinion, you shouldn't do image processing directly on bitmaps. You should use bitmaps when loading from a file, displaying on screen, and saving to a file. Your filters should work on the pixels, whatever format they are.

I suggest your filters work on BYTE or float array, or RGBQUAD arrays.

This post contains usefull code and links for using Bitmaps:
CBitmap::CreateBitmap: How to !?[^]

You can also use a helper class to store image pixels:
Passing 2D Arrays to functions[^]
This one is in C#, but you can easily conver it:
Problem storing image matrix[^]
 
Share this answer
 
Comments
Niklas L 26-Apr-11 8:03am    
Good advice. 5.
Olivier Levrey 26-Apr-11 8:36am    
Thank you Niklas.
Mr. Tomay 27-Apr-11 18:40pm    
look at my new post please
I've realized about 60% of my project except one thing: When loading some BMP images the app crashes, here is my code source:
ECAEDDoc.h
// ECAEDDoc.h : interface of the CECAEDDoc class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_ECAEDDOC_H__64E67B6C_E0ED_4F6D_8A70_2387DE188471__INCLUDED_)
#define AFX_ECAEDDOC_H__64E67B6C_E0ED_4F6D_8A70_2387DE188471__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CECAEDDoc : public CDocument
{
protected: // create from serialization only
	CECAEDDoc();
	DECLARE_DYNCREATE(CECAEDDoc)
// Attributes
public:
	CBitmap m_bmpIn;
	CBitmap m_bmpOut;
// Operations
public:
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CECAEDDoc)
	public:
	virtual BOOL OnNewDocument();
	virtual void Serialize(CArchive& ar);
	virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
	//}}AFX_VIRTUAL
// Implementation
public:
	virtual ~CECAEDDoc();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
	//{{AFX_MSG(CECAEDDoc)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ECAEDDOC_H__64E67B6C_E0ED_4F6D_8A70_2387DE188471__INCLUDED_)


ECAEDDoc.cpp
// ECAEDDoc.cpp : implementation of the CECAEDDoc class
//
#include "stdafx.h"
#include "ECAED.h"
#include "ECAEDDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CECAEDDoc
IMPLEMENT_DYNCREATE(CECAEDDoc, CDocument)
BEGIN_MESSAGE_MAP(CECAEDDoc, CDocument)
	//{{AFX_MSG_MAP(CECAEDDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CECAEDDoc construction/destruction
CECAEDDoc::CECAEDDoc()
{
	// TODO: add one-time construction code here
}
CECAEDDoc::~CECAEDDoc()
{
}
BOOL CECAEDDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;
	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CECAEDDoc serialization
void CECAEDDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}
/////////////////////////////////////////////////////////////////////////////
// CECAEDDoc diagnostics
#ifdef _DEBUG
void CECAEDDoc::AssertValid() const
{
	CDocument::AssertValid();
}
void CECAEDDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CECAEDDoc commands
BOOL CECAEDDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
	
	// TODO: Add your specialized creation code here
	// Load the selected bitmap file
	HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, lpszPathName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
	
	// Do we have a valid handle for the loaded image?
	if (hBitmap)
	{
		// Delete the current bitmap
		m_bmpIn.DeleteObject();
		
		// Attach the currently loaded bitmap to the bitmap object
		m_bmpIn.Attach(hBitmap);
	}
	DIBSECTION ds;
	
	::GetObject(hBitmap, sizeof(DIBSECTION), &ds);
	BITMAPINFO bmi;
	LPBYTE pBits = (LPBYTE)ds.dsBm.bmBits;
	LPBYTE pBitsOut;
	HBITMAP hBitmapOut;
	// Initialize header to 0s.
	ZeroMemory(&bmi, sizeof(bmi));
	// Fill out the fields you care about.
	bmi.bmiHeader = ds.dsBmih;
	hBitmapOut = CreateDIBSection(GetDC(NULL), &bmi, DIB_RGB_COLORS, (LPVOID*)&pBitsOut, NULL, 0);
	if (!hBitmap || !pBitsOut)
		return NULL;
	
	// Do we have a valid handle for the created image?
	if (hBitmapOut)
	{
		// Delete the current bitmap
		m_bmpOut.DeleteObject();
		
		// Attach the currently loaded bitmap to the bitmap object
		m_bmpOut.Attach(hBitmapOut);
	}
	DIBSECTION dsOut;
	
	::GetObject(hBitmapOut, sizeof(DIBSECTION), &dsOut);
	
	::SetDIBits(GetDC(NULL), hBitmapOut, 0, dsOut.dsBm.bmHeight, pBits, &bmi, DIB_RGB_COLORS);
	
	int Mask[3][3] = {{-2, -1, -2},
					  {-1, 12, -1},
					  {-2, -1, -2}};
	int sumR;
	int sumG;
	int sumB;
	
	for (int y = 0; y < dsOut.dsBm.bmHeight; y ++)
		for (int x = 0; x < dsOut.dsBm.bmWidth; x ++)
		{
			sumR = 0;
			sumG = 0;
			sumB = 0;
			for (int i = 0; i < 3; i ++)
			{
				if ((y + i - 1) < 0 || (y + i - 1) > dsOut.dsBm.bmHeight)
						continue;
				for (int j = 0; j < 3; j ++)
				{
					if ((x + j - 1) < 0 || (x + j - 1) > dsOut.dsBm.bmWidth)
						continue;
					
					sumB += pBits[(y + i - 1) * ds.dsBm.bmWidthBytes + (x * ds.dsBm.bmBitsPixel / 8) + j - 1] * Mask[i][j] / 2;
					sumG += pBits[(y + i - 1) * ds.dsBm.bmWidthBytes + (x * ds.dsBm.bmBitsPixel / 8) + j - 1 + 1] * Mask[i][j] / 2;
					sumR += pBits[(y + i - 1) * ds.dsBm.bmWidthBytes + (x * ds.dsBm.bmBitsPixel / 8) + j - 1 + 2] * Mask[i][j] / 2;
				}
			}
			if (sumR < 0)
				sumR = 0;
			if (sumR > 255)
				sumR = 255;
			if (sumG < 0)
				sumG = 0;
			if (sumG > 255)
				sumG = 255;
			if (sumB < 0)
				sumB = 0;
			if (sumB > 255)
				sumB = 255;
			pBitsOut[y * dsOut.dsBm.bmWidthBytes + (x * dsOut.dsBm.bmBitsPixel / 8)] = sumB;
			pBitsOut[y * dsOut.dsBm.bmWidthBytes + (x * dsOut.dsBm.bmBitsPixel / 8) + 1] = sumG;
			pBitsOut[y * dsOut.dsBm.bmWidthBytes + (x * dsOut.dsBm.bmBitsPixel / 8) + 2] = sumR;
		}
		
		return TRUE;
}


and here is a screenshot of the app:


I don't know how to fix it !?
 
Share this answer
 
Comments
Olivier Levrey 28-Apr-11 4:55am    
You say "it crashes" but where? You should use the debugger to find where, and you will maybe even be able to fix it by yourself.
Mr. Tomay 28-Apr-11 14:20pm    
I found the problem issue, it was an array index out of bounds
if ((y + i - 1) < 0 || (y + i - 1) > dsOut.dsBm.bmHeight) should be
if ((y + i - 1) < 0 || (y + i - 1) >= dsOut.dsBm.bmHeight)
and
if ((x + j - 1) < 0 || (x + j - 1) > dsOut.dsBm.bmWidth) should be
if ((x + j - 1) < 0 || (x + j - 1) >= dsOut.dsBm.bmWidth)

It seems that I am very weak in C++ programming ;)
Olivier Levrey 29-Apr-11 3:43am    
We are all learning from our mistakes ;)
Keep going
Mr. Tomay 29-Apr-11 16:48pm    
Thanks
1. Compile the Debug version of your app.

2. Run your app under the debugger.

3. When it crashes, choose "Retry".

4. The debugger will show you the line where it crashed.

5. Look at variables that are referenced in that line. Most likely, it will be a pointer of some kind, or an array index out of bounds.

6. Post again here if you can't figure it out.
 
Share this answer
 
Comments
Mr. Tomay 27-Apr-11 19:08pm    
ah! I'll try ;)
Mr. Tomay 28-Apr-11 14:27pm    
I found the problem issue, it was an array index out of bounds
if ((y + i - 1) < 0 || (y + i - 1) > dsOut.dsBm.bmHeight) should be
if ((y + i - 1) < 0 || (y + i - 1) >= dsOut.dsBm.bmHeight)
and
if ((x + j - 1) < 0 || (x + j - 1) > dsOut.dsBm.bmWidth) should be
if ((x + j - 1) < 0 || (x + j - 1) >= dsOut.dsBm.bmWidth)

It seems that I am very weak in C++ programming ;)

I am facing other problems in bitmap processing when the bitmap is a palette (indexed mode) not (RGB mode) and also when the bitmap is an bottom-up aligned.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900