Unsigned char * buffer in System :: Drawing :: Bitmap

I am trying to create a tool / asset converter that rasterizes a font to a texture page for an XNA game using the FreeType2 engine.

Below the first image is a direct exit from the FreeType2] 1 mechanism. The second image is the result after converting it to System::Drawing::Bitmap .

target http://www.freeimagehosting.net/uploads/fb102ee6da.jpg currentresult http://www.freeimagehosting.net/uploads/9ea77fa307.jpg

Any hints / tips / ideas about what is going on here would be greatly appreciated. Links to articles explaining layout layouts and pixel formats will also be helpful.

  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"); 

Update . Changed PixelFormat to 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); 
+4
source share
2 answers

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); 
+6
source

Depth does not match the PixelFormat bitmap. To match Format24bppRgb, there should be 24. PF for the bitmap must also match PF and the FT_Bitmap step, I don’t see you take care of this.

+1
source

Source: https://habr.com/ru/post/924854/


All Articles