74705

Indexing pixels in a monochrome FreeType glyph buffer

Question:

I want to translate a monochrome FreeType glyph to an RGBA unsigned byte OpenGL texture. The colour of the texture at pixel (x, y) would be (255, 255, alpha), where

alpha = glyph->bitmap.buffer[pixelIndex(x, y)] * 255

I load my glyph using

FT_Load_Char(face, glyphChar, FT_LOAD_RENDER | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO)

The target texture has dimensions of glyph->bitmap.width * glyph->bitmap.rows. I've been able to index a greyscale glyph (loaded using just FT_Load_Char(face, glyphChar, FT_LOAD_RENDER)) with

glyph->bitmap.buffer[(glyph->bitmap.width * y) + x]

This does not appear work on a monochrome buffer though and the characters in my final texture are scrambled.

What is the correct way to get the value of pixel (x, y) in a monochrome glyph buffer?

Answer1:

Based on <a href="http://www.gamedev.net/topic/638764-indexing-pixels-in-monochrome-freetype-glyph/" rel="nofollow">this thread I started on Gamedev.net</a>, I've come up with the following function to get the filled/empty state of the pixel at (x, y):

bool glyphBit(const FT_GlyphSlot &glyph, const int x, const int y) { int pitch = abs(glyph->bitmap.pitch); unsigned char *row = &glyph->bitmap.buffer[pitch * y]; char cValue = row[x >> 3]; return (cValue & (128 >> (x & 7))) != 0; }

Answer2:

I have a similiar question some time ago. So I would to try help you.

<blockquote>

The target texture has dimensions of glyph->bitmap.width * glyph->bitmap.rows

</blockquote>

This is very specific dimension for OpenGl. Would be better if you round this to power of two.

In common way you make cycle where you get every glyph. Then cycle for every row from 0 to glyph->bitmap.rows. Then cycle for every byte (unsigned char) in row from 0 to glyph->pitch. Where you get byte by handling glyph->bitmap.buffer[pitch * row + i] (i is index of inner cycle and row is index of outer). For example:

if(s[i] == ' ') left += 20; else for (int row = 0; row < g->bitmap.rows; ++row) { if(kerning) for(int b = 0; b < pitch; b++){ if(data[left + 64*(strSize*(row + 64 - g->bitmap_top)) + b] + g->bitmap.buffer[pitch * row + b] < UCHAR_MAX) data[left + 64*(strSize*(row + 64 - g->bitmap_top)) + b] += g->bitmap.buffer[pitch * row + b]; else data[left + 64*(strSize*(row + 64 - g->bitmap_top)) + b] = UCHAR_MAX; } else std::memcpy(data + left + 64*(strSize*(row + 64 - g->bitmap_top)) , g->bitmap.buffer + pitch * row, pitch); } left += g->advance.x >> 6;

This code is relevant to an 8-bit bitmap (standart FT_Load_Char(face, glyphChar, FT_LOAD_RENDER)). Now I tried to use the monochrome flag and it caused me trouble. So my answer is not a solution to your problem. If you just want to display the letter then you should see my <a href="https://stackoverflow.com/questions/14800667/incorrect-output-texture-on-quad" rel="nofollow">question</a>.

Answer3:

The following Python function unpacks a FT_LOAD_TARGET_MONO glyph bitmap into a more convenient representation where each byte in the buffer maps to one pixel.

I've got some more info on monochrome font rendering with Python and FreeType plus additional example code on my blog: <a href="http://dbader.org/blog/monochrome-font-rendering-with-freetype-and-python" rel="nofollow">http://dbader.org/blog/monochrome-font-rendering-with-freetype-and-python</a>

<pre class="lang-py prettyprint-override">def unpack_mono_bitmap(bitmap): """ Unpack a freetype FT_LOAD_TARGET_MONO glyph bitmap into a bytearray where each pixel is represented by a single byte. """ # Allocate a bytearray of sufficient size to hold the glyph bitmap. data = bytearray(bitmap.rows * bitmap.width) # Iterate over every byte in the glyph bitmap. Note that we're not # iterating over every pixel in the resulting unpacked bitmap -- # we're iterating over the packed bytes in the input bitmap. for y in range(bitmap.rows): for byte_index in range(bitmap.pitch): # Read the byte that contains the packed pixel data. byte_value = bitmap.buffer[y * bitmap.pitch + byte_index] # We've processed this many bits (=pixels) so far. This determines # where we'll read the next batch of pixels from. num_bits_done = byte_index * 8 # Pre-compute where to write the pixels that we're going # to unpack from the current byte in the glyph bitmap. rowstart = y * bitmap.width + byte_index * 8 # Iterate over every bit (=pixel) that's still a part of the # output bitmap. Sometimes we're only unpacking a fraction of a byte # because glyphs may not always fit on a byte boundary. So we make sure # to stop if we unpack past the current row of pixels. for bit_index in range(min(8, bitmap.width - num_bits_done)): # Unpack the next pixel from the current glyph byte. bit = byte_value & (1 << (7 - bit_index)) # Write the pixel to the output bytearray. We ensure that `off` # pixels have a value of 0 and `on` pixels have a value of 1. data[rowstart + bit_index] = 1 if bit else 0 return data

Recommend

  • EXCEL VBA - Convert comma separated values to different columns
  • SELECT DISTINCT in mysqli prepared statement?
  • Repeat audio clip in Unity, with increasingly smaller intervals
  • Google Streetview: Conversion between FOV and Zoom
  • Loop over multiple file extensions from bash script
  • Qt - Cannot get lambda to work [duplicate]
  • sql left join returns
  • Linked list in C, no member error
  • combination of two lists in java
  • Implicit cast from const string to bool [duplicate]
  • UIimage to char* conversion
  • std::system Exception when instantiating a singleton object
  • Load 24 bit TGA
  • Get the App path without the app name at the end of the app
  • Partial specialization of a class template in derived class affects base class
  • Arduino making decision according to a packet received from serial port
  • Invert string in Rust
  • Changing a global variable in C
  • How to unpack 32bit integer packed in a QByteArray?
  • powershell Get-Counter -ComputerName parameter on Windows 7
  • How to read piped content in C?
  • Invalid Date on validation Date of js
  • std::remove_copy_if_ valgrind bytes in block are possibly lost in loss record
  • Appending Character to Character Array In C
  • C: Incompatible pointer type initializing
  • AES padding and writing the ciphertext to a disk file
  • VS2008 Enable C++ Exception with SEH
  • MySQL WHERE-condition in procedure ignored
  • Convert array of 8 bytes to signed long in C++
  • Rearranging Cells in UITableView Bug & Saving Changes
  • Circular dependency while pushing http interceptor
  • using conditional logic : check if record exists; if it does, update it, if not, create it
  • Linker errors when using intrinsic function via function pointer
  • How get height of the a view with gone visibility and height defined as wrap_content in xml?
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • LevelDB C iterator
  • Can't mass-assign protected attributes when import data from csv file
  • Sorting a 2D array using the second column C++
  • Unable to use reactive element in my shiny app
  • java string with new operator and a literal