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, и как зовут данный формат, точного определения что это - не нашел.
В результате получился такой вот конвертер с 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;
}
Фрилансер или Digital-агентство - Как сделать правильный выбор?
Одна программа, включающая хэдер с классами и его cpp с методами, генерирует данныеНеобходимо эти данные сохранять в БД
Не могу найти однозначного ответа на следующий вопрос