0
votes

I'm developping a thumbnail creator as a shell extension.

To do that, I choosed to implement interface IExtractImage.

My dll is loaded and correctly called, but, the thumbnail is always black, instead of being red.

What am I missing?

class MyShellPreview : public IExtractImage, IPersistFile

    // set by IExtractImage::GetLocation
    SIZE m_size;


    IFACEMETHODIMP Extract(HBITMAP *phBmpImage)
    {
        size_t size = m_size.cx * m_size.cy * 3;

        // alloc buffer
        BYTE *buffer = (BYTE*)malloc(size);

        // fill buffer
        for (k = i = 0; i < m_size.cx; ++i)
        {
            for (j = 0; j < m_size.cy; ++j, ++k)
            {
                buffer[k] = 128;
                buffer[k+1] = 0;
                buffer[k+2] = 0;
            }
        }

        *phBmpImage = CreateBitmap(m_size.cx, m_size.cy, 3, 8, buffer);

        free(buffer);

        return S_OK;
    }        
};

I know that for performance reason, I should use CreateCompatibleBitmap and SetDIBits, but I'm not sure from where I should get an HDC.

1
You do not have 3 color planes, so the second parameter to CreateBitmap should be 1. Aside from that, I strongly suggest creating 32-bpp bitmaps, since that's what all modern graphics hardware uses internally. It will save the need to do conversions and make your life simpler, too. Remember that in Windows, because it's little-endian, the BGRA format is used. - Cody Gray
Thanks. I started with CreateBitmap(m_size.cx, m_size.cy, 1, 8, buffer) without success, I just try with CreateBitmap(m_size.cx, m_size.cy, 1, 32, buffer), it seems to be much better... - Mathieu
Right. You are filling it as if it is a 32-bpp image. 8-bpp is an indexed format, and you hadn't set up the palette. All of this information on color formats is documented on MSDN and elsewhere, but it's complicated and you don't need to worry about it if you just use 32-bpp formats like everyone else nowadays. - Cody Gray
Since you are using a 24bpp buffer, you need to pass 24 for cBitsPerPel. And you need to DWORD-align scanlines in your buffer. Or go straight with 32bpp data (which is automatically properly aligned). - IInspectable
You also never change k, so you aren't filling or manipulating anything other than the first pixel, regardless of what the comments above say! You will need to fix all these issues at the same time to make this work. - andlabs

1 Answers

0
votes

As pointed on comments, the solution was to use:

  • 32 bits images
  • 1 color plane


class MyShellPreview : public IExtractImage, IPersistFile

    // set by IExtractImage::GetLocation
    SIZE m_size;

    IFACEMETHODIMP Extract(HBITMAP *phBmpImage)
    {
        size_t size = m_size.cx * m_size.cy * 4;

        // alloc buffer
        BYTE *buffer = (BYTE*)calloc(size, 1);

        // fill buffer
        for (k = i = 0; i < m_size.cx; ++i)
        {
            for (j = 0; j < m_size.cy; ++j, k+=4)
            {
                buffer[k] = 128;                    
            }
        }

        *phBmpImage = CreateBitmap(m_size.cx, m_size.cy, 1, 24, buffer);

        free(buffer);

        return S_OK;
    }        
};