Результат screencap RAW в Bitmap

132
13 декабря 2019, 01:10

Screencap на Android умеет отдавать RAW картинку, как я понимаю, это framebuffer с заголовком. Как правильно привести данные RAW к формату Bmp?

Читаю со смещением 16 байт, судя по исходникам https://android.googlesource.com/platform/frameworks/base/+/master/cmds/screencap/screencap.cpp

  uint32_t c = dataSpaceToInt(d);
    write(fd, &w, 4);
    write(fd, &h, 4);
    write(fd, &f, 4);
    write(fd, &c, 4);
    size_t Bpp = bytesPerPixel(f);
    for (size_t y=0 ; y<h ; y++) {
        write(fd, base, w*Bpp);
        base = (void *)((char *)base + s*Bpp);
    }

А как правильно разобрать остальные данные? попытка читать как RGBA не даёт результата, изображение не получается..

Возможно есть готовый вариант, как из этого формата перевести в .bmp, и как зовут данный формат, точного определения что это - не нашел.

Answer 1

В результате получился такой вот конвертер с win32 API в плане заголовков Bitmap, предполагается что raw 32 bpp. Остался правда вопрос, как добыть из raw bbp 16/24/32 .. буду рад совету на эту тему.

Добываем raw в вектор, и из первых 12 байтов берем информацию о свойствах экрана:

if (v.size() < 12)
    return false;
unsigned long width   = *(unsigned long*)&v[0];
unsigned long height  = *(unsigned long*)&v[4];
unsigned long flag    = *(unsigned long*)&v[8];
unsigned long rawsize = static_cast<unsigned long>(width * height * 4 + 12);
if (v.size() != rawsize)
    return false;

Функция конвертации в .bmp:

bool SaveRawToBitmap(std::vector<char> & v,
                       DWORD w,
                       DWORD h,
                       DWORD bpp,
                       LPCTSTR fname )
{
    FILE *fout;
    int bmppad = ((w * 3) % 3);
    if (bmppad != 0)
        bmppad = 3 - bmppad;
    DWORD bmpsize = static_cast<DWORD>((w * 3 + bmppad) * h);
    BITMAPINFOHEADER bmpi;
    BITMAPFILEHEADER bmph;
    ZeroMemory(&bmpi, sizeof(bmpi));
    ZeroMemory(&bmph, sizeof(bmph));
    bmpi.biSize = sizeof(bmpi);
    bmpi.biWidth = w;
    bmpi.biHeight = h;
    bmpi.biPlanes = 1;
    bmpi.biBitCount = bpp; /// 24 bpp - схема сохранения
    bmpi.biCompression = BI_RGB;
    bmph.bfOffBits = static_cast<DWORD>(sizeof(bmph) + sizeof(bmpi));
    bmph.bfSize = static_cast<DWORD>(
                      bmpsize
                      + sizeof(bmph)
                      + sizeof(bmpi)
                  );
    bmph.bfType = 0x4D42;
    if (!(fout = fopen(fname, "wb")))
        return false;
    fwrite(&bmph, sizeof(bmph), 1, fout);
    fwrite(&bmpi, sizeof(bmpi), 1, fout);
    DWORD wsize = (w * 4);
    DWORD64 tsize = 0LLU;
    std::vector<BYTE> vbmp(h * (w * 3));
    std::vector<BYTE> vw(wsize);
    v.erase(v.begin(), v.begin()+12);
    std::reverse(v.begin(), v.end());
    for(DWORD y = 0U, i = 0U; y < h; y++, i += wsize)
    {
        std::vector<BYTE> vw(wsize);
        vw.assign(
                  reinterpret_cast<PBYTE>(&v[i]),
                  reinterpret_cast<PBYTE>(&v[i + wsize])
                );
        std::reverse(vw.begin(), vw.end());
        for (DWORD x = 0U; x < vw.size(); x += 4)
        {
            vbmp[tsize++] = vw[(x + 2)];
            vbmp[tsize++] = vw[(x + 1)];
            vbmp[tsize++] = vw[(x + 0)];
        }
    }
    fwrite(&vbmp[0], vbmp.size(), 1, fout);
    fclose(fout);
    return true;
}
READ ALSO
Как подключить к Visual Studio 2017 ODB, работающий с SQLite

Как подключить к Visual Studio 2017 ODB, работающий с SQLite

Одна программа, включающая хэдер с классами и его cpp с методами, генерирует данныеНеобходимо эти данные сохранять в БД

109
Правильный способ обратиться к полю не выровненного объекта

Правильный способ обратиться к полю не выровненного объекта

Не могу найти однозначного ответа на следующий вопрос

102
Использование proto в Qt

Использование proto в Qt

Задача: подключиться с вебсокету livecoinnet (https://github

110