Yeah. I worked.
FT_Bitmap is an 8-bit image, so the correct PixelFormat was 8bppIndexed , which led to this conclusion. Does not align with 32 bytes border http://www.freeimagehosting.net/uploads/dd90fa2252.jpg
System::Drawing::Bitmap needs to be aligned on a 32-bit boundary.
I calculated the step, but did not add it when writing a bitmap. I copied the FT_Bitmap buffer in byte[] , and then wrote it to a MemoryStream , adding the necessary padding.
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); }
Attached to the memory so that the GC leaves him alone.
// 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();
Since there is no Format8bppIndexed Gray, the image is still not correct.
alt text http://www.freeimagehosting.net/uploads/8a883b7dce.png
Then the raster image palette changed to a gray scale of 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
The final decision.
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);