0

I obtain a CF_DIB from a clipboard and then call:

GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(info->bmiColors, GDK_COLORSPACE_RGB, TRUE, 8, info->bmiHeader.biWidth, info->bmiHeader.biHeight, rowstride, NULL, NULL);

to create a GdkPixbuf out of the pixel data. However the image appears to be flipped upside down and mirrored inverted (I think as it is BGR).

How do I create the pixbuf properly?

Edenia
  • 2,312
  • 1
  • 16
  • 33
  • If nothing helps (and no solution provided here), you can always invert it again and flip it again. – Paul Ogilvie Jun 23 '19 at 19:52
  • 3
    This MS page about [Device-Independent Bitmaps](https://learn.microsoft.com/en-us/windows/desktop/gdi/device-independent-bitmaps) says *...if the height is a negative value, it is a top-down DIB.* – Weather Vane Jun 23 '19 at 20:58
  • @WeatherVane Which are rare; normally bitmaps are stored upside down (bottom-up). – user253751 Jun 23 '19 at 22:58
  • some images contain [EXIF](https://en.wikipedia.org/wiki/Exif) extension (regardles of the image fileformat) which contains info about rotation,flipping so make sure its not just flipped in it, Many tools rotate images just by setting a flag in this structure instead of manipulating the pixels itself. And many tools/libs do not recognize EXIF having troubles like you do ... PS if you solved your problem you should mark your answer as accepted ... – Spektre Dec 09 '19 at 09:30
  • @Spektre I've heard about it, but I think it does not apply for bitmaps. – Edenia Dec 09 '19 at 14:50
  • @Edenia it applies to any image bitmaps included ... the EXIF is usually added to end of file (without any changes in original image format). However if fileformat allows extentions it can be placed there too (which is usually near start of file). Open in hex viewer and look for `Exif` signature. – Spektre Dec 09 '19 at 15:45

1 Answers1

0

I solved my problem with this function I wrote:

GdkPixbuf* soft_drm_dib_to_pixbuf (BITMAPINFO* info)
{
    gint    rowstride   = 4 * ((info->bmiHeader.biBitCount * info->bmiHeader.biWidth + 31) / 32);
    gsize   size        = rowstride * info->bmiHeader.biHeight;
    gchar*  copy        = (gchar *)info->bmiColors;
    gchar*  newp        = g_malloc0(size);
    gint    x           = 0;
    gint    y           = 0;

    for(y = 0; y < info->bmiHeader.biHeight; y++)
    {
        for(x = 0; x < info->bmiHeader.biWidth; x++)
        {
            gint    col     = x;
            gint    row     = info->bmiHeader.biHeight - y - 1;
            gint    index   = (row * info->bmiHeader.biWidth + col) * 4;
            gint    index2  = (row * info->bmiHeader.biWidth + (info->bmiHeader.biWidth - col)) * 4;

            newp[(size - index2) + 0] = copy[index + 2];
            newp[(size - index2) + 1] = copy[index + 1];
            newp[(size - index2) + 2] = copy[index + 0];
        }
    }

    return gdk_pixbuf_new_from_data(newp, GDK_COLORSPACE_RGB, TRUE, 8, info->bmiHeader.biWidth, info->bmiHeader.biHeight, rowstride, (GdkPixbufDestroyNotify)g_free, NULL);
}

it definitely can look much better though.

Edenia
  • 2,312
  • 1
  • 16
  • 33
  • You need to use `rowstride` inside your loop (if you plan to use that code for bitmaps with a bpp count other than 4). – IInspectable Jun 24 '19 at 11:22
  • and padding. When used as a cairo source, the whole area is black, but the pixbuf itself is valid hmm. – Edenia Jun 24 '19 at 12:05
  • that would be, because alpha bytes are 0 I think. I should do `newp[(size - index2) + 3] = 255;` at leasts. – Edenia Jun 24 '19 at 12:10