Solving linker error ‘LNK2022: metadata operation failed’

If you are compiling managed C++ projects, and ever encountered this idiotic linker error:

1>xxx.obj : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (_PROPSHEETPAGEW): (0x020001f8).

1>xxx.obj : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (_PROPSHEETPAGEA): (0x02000206).

than this post is for you.

For some reason in our code, this linker error always comes in pairs. No matter, in our code base it usually manifests itself after rearranging header files in a file that is compiled with /clr compiler switch.

The problem is caused by windows.h being included after other header files:

#pragma unmanaged
#include “file.h”
#include “otherfile.h”
#include <windows.h>

#pragma managed
….

The solution is to make sure that windows.h is included before anything else.

#pragma unmanaged
#include <windows.h>
#include “file.h”
#include “otherfile.h”

#pragma managed

….

Advertisements

How to display a Bitmap with Gamma Correction in Autodesk 3dsmax

A customer asked me the other day how to display a Bitmap with the gamma correction. He was writing a custom maxscript UI control, and wanted to display a maxscript bitmap on the UI control. Ok, fair enough. Once he displayed the image, he found the image displayed as too dark. The same problem was found with the ImgTag maxscript UI control (found in maxsdksamplesmaxscriptmxsagniimgtag.cpp). A bitmap displayed in the ImgTag control was also displayed as too dark. This maxscript showed the problem when ran in 3dsmax 2012:

p = "E:\Dev\defects\chris_haydon_100.jpg"
b = openbitmap p
display b

rollout TOO_DARK "too dark imgtag"
(
    imgtag n "fish" bitmap:b
)
createDialog TOO_DARK width:400 height:400

What you would see is the Image on the maxscript dialog UI control would be too dark, while the image displayed in the normal maxscript bitmap would be normal.

The reason is because starting in 3dsmax 2012, gamma settings were turned on by default. In previous versions it was turned off. And the ImgTag code completely ignored gamma settings.

To display a Bitmap (maxsdkincludebitmap.h) correctly you have to pass in TRUE for the last parameter to

Bitmap::ToDib( int depth, UWORD *gam, BOOL dither, BOOL displayGamma )

This is used in code like this:

PBITMAPINFO bmi = mbm->bm->ToDib(32, NULL, FALSE, TRUE);

So for instance, the ImgTag was fixed to display a bitmap correctly with gamma in the following code:

Code Snippet
int ImgTag::SetBitmap(Value* val)
{
    if(val == &undefined)
    {
        if(m_hBitmap) DeleteObject(m_hBitmap);
        m_hBitmap = NULL;
        m_maxBitMap = NULL;
    }
    else
    {
        HWND hWnd = MAXScript_interface->GetMAXHWnd();

        MAXBitMap* mbm = (MAXBitMap*)val;
        type_check(mbm, MAXBitMap, _T("set .bitmap"));
        m_maxBitMap = val;

        HDC hDC = GetDC(hWnd);
        PBITMAPINFO bmi = mbm->bm->ToDib(32, NULL, FALSE, TRUE);
        if(m_hBitmap)
            DeleteObject(m_hBitmap);
        m_hBitmap = CreateDIBitmap(hDC, &bmi->bmiHeader, CBM_INIT, bmi->bmiColors, bmi, DIB_RGB_COLORS);
        LocalFree(bmi);
        ReleaseDC(hWnd, hDC);
    }

    Invalidate();
    return 1;
}