Unsigned char* Buffer to System :: Brate :: Bitmap
-
02-10-2019 - |
Вопрос
Я пытаюсь создать преобразователь инструментов/активов, который растеряет шрифт на страницу текстуры для игры XNA, используя Freetype2 двигатель.
Ниже первое изображение является прямым выводом Freetype21 двигатель. Второе изображение является результатом после попытки преобразовать его в System::Drawing::Bitmap
.
Target http://www.freeimagehosting.net/uploads/fb102ee6da.jpg CurrentResult http://www.freeimagehosting.net/uploads/9ea77fa307.jpg
Любые подсказки/подсказки/идеи о том, что здесь происходит, были бы очень оценены. Ссылки на статьи, объясняющие макет байта и форматы пикселей, также были бы полезны.
FT_Bitmap *bitmap = &face->glyph->bitmap;
int width = (face->bitmap->metrics.width / 64);
int height = (face->bitmap->metrics.height / 64);
// must be aligned on a 32 bit boundary or 4 bytes
int depth = 8;
int stride = ((width * depth + 31) & ~31) >> 3;
int bytes = (int)(stride * height);
// as *.bmp
array<Byte>^ values = gcnew array<Byte>(bytes);
Marshal::Copy((IntPtr)glyph->buffer, values, 0, bytes);
Bitmap^ systemBitmap = gcnew Bitmap(width, height, PixelFormat::Format24bppRgb);
// create bitmap data, lock pixels to be written.
BitmapData^ bitmapData = systemBitmap->LockBits(Rectangle(0, 0, width, height), ImageLockMode::WriteOnly, bitmap->PixelFormat);
Marshal::Copy(values, 0, bitmapData->Scan0, bytes);
systemBitmap->UnlockBits(bitmapData);
systemBitmap->Save("Test.bmp");
Обновлять. Анкет Изменено Pixelformat на 8bppIndexed
.
FT_Bitmap *bitmap = &face->glyph->bitmap;
// stride must be aligned on a 32 bit boundary or 4 bytes
int depth = 8;
int stride = ((width * depth + 31) & ~31) >> 3;
int bytes = (int)(stride * height);
target = gcnew Bitmap(width, height, PixelFormat::Format8bppIndexed);
// create bitmap data, lock pixels to be written.
BitmapData^ bitmapData = target->LockBits(Rectangle(0, 0, width, height), ImageLockMode::WriteOnly, target->PixelFormat);
array<Byte>^ values = gcnew array<Byte>(bytes);
Marshal::Copy((IntPtr)bitmap->buffer, values, 0, bytes);
Marshal::Copy(values, 0, bitmapData->Scan0, bytes);
target->UnlockBits(bitmapData);
Решение
Ах ха. Выработал это.
FT_Bitmap
8 -битное изображение, так что правильное PixelFormat
был 8bppIndexed
, что привело к этому выводу.Не выровнен по границе 32BYTE http://www.freeimagehosting.net/uploads/dd90fa2252.jpg
System::Drawing::Bitmap
необходимо выровнять на 32 -битной границе.
Я рассчитывал шаг, но не заполнял его при написании растрового изображения. Скопировал FT_Bitmap
буфер к byte[]
а затем написал это MemoryStream
, добавив необходимую прокладку.
int stride = ((width * pixelDepth + 31) & ~31) >> 3;
int padding = stride - (((width * pixelDepth) + 7) / 8);
array<Byte>^ pad = gcnew array<Byte>(padding);
array<Byte>^ buffer = gcnew array<Byte>(size);
Marshal::Copy((IntPtr)source->buffer, buffer, 0, size);
MemoryStream^ ms = gcnew MemoryStream();
for (int i = 0; i < height; ++i)
{
ms->Write(buffer, i * width, width);
ms->Write(pad, 0, padding);
}
Закрепил память, чтобы GC оставил ее в покое.
// pin memory and create bitmap
GCHandle handle = GCHandle::Alloc(ms->ToArray(), GCHandleType::Pinned);
target = gcnew Bitmap(width, height, stride, PixelFormat::Format8bppIndexed, handle.AddrOfPinnedObject());
ms->Close();
Поскольку нет Format8bppIndexed
Серый Изображение все еще не было правильным.
Alt Text http://www.freeimagehosting.net/uploads/8a883b7dce.png
Затем изменил растровую палитру на серую шкалу 256.
// 256-level greyscale palette
ColorPalette^ palette = target->Palette;
for (int i = 0; i < palette->Entries->Length; ++i)
palette->Entries[i] = Color::FromArgb(i,i,i);
target->Palette = palette;
Alt Text http://www.freeimagehosting.net/uploads/59a745269e.jpg
Окончательное решение.
error = FT_Load_Char(face, ch, FT_LOAD_RENDER);
if (error)
throw gcnew InvalidOperationException("Failed to load and render character");
FT_Bitmap *source = &face->glyph->bitmap;
int width = (face->glyph->metrics.width / 64);
int height = (face->glyph->metrics.height / 64);
int pixelDepth = 8;
int size = width * height;
// stride must be aligned on a 32 bit boundary or 4 bytes
// padding is the number of bytes to add to make each row a 32bit aligned row
int stride = ((width * pixelDepth + 31) & ~31) >> 3;
int padding = stride - (((width * pixelDepth) + 7) / 8);
array<Byte>^ pad = gcnew array<Byte>(padding);
array<Byte>^ buffer = gcnew array<Byte>(size);
Marshal::Copy((IntPtr)source->buffer, buffer, 0, size);
MemoryStream^ ms = gcnew MemoryStream();
for (int i = 0; i < height; ++i)
{
ms->Write(buffer, i * width, width);
ms->Write(pad, 0, padding);
}
// pin memory and create bitmap
GCHandle handle = GCHandle::Alloc(ms->ToArray(), GCHandleType::Pinned);
target = gcnew Bitmap(width, height, stride, PixelFormat::Format8bppIndexed, handle.AddrOfPinnedObject());
ms->Close();
// 256-level greyscale palette
ColorPalette^ palette = target->Palette;
for (int i = 0; i < palette->Entries->Length; ++i)
palette->Entries[i] = Color::FromArgb(i,i,i);
target->Palette = palette;
FT_Done_FreeType(library);
Другие советы
Ваше значение «глубины» не соответствует Pixelformat растровой карты. Это должно быть 24, чтобы соответствовать формату24BPPRGB. PF для растрового изображения должен соответствовать PF и шагу FT_BITMAP, я не вижу, чтобы вы позаботились об этом.