Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » al_autocrop_bitmap() ?

This thread is locked; no one can reply to it. rss feed Print
al_autocrop_bitmap() ?
alehbeer
Member #12,996
July 2011
avatar

How would one have a function such as al_autocrop_bitmap() that would get rid of extra space if all pixels are transparent? I think I would use something like

void crop_bmp(BITMAP ** bmp, int ix, int iy, int fx , int fy){
  BITMAP * temp;

  temp = create_bitmap(fx-ix, fy-iy);
  clear_to_color(temp, MAGENTA);

  draw_sprite(temp,*bmp,-ix,-iy);

  destroy_bitmap(*bmp);
  *bmp = temp;
}

found at https://www.allegro.cc/forums/thread/607897

But I want to remove edge line by line from top,bottom, left, and right if it is transparent. How can I check if a pixel is transparent in allegro? Should I draw onto a FrameBuffer and then get pixel from that? Is this the right way of doing this?

jmasterx
Member #11,410
October 2009

I have some old code from a Bitmap triangulator that found the contour of a bitmap by seeking through its transparent pixels:

#SelectExpand
1 void ImagePolygon::computeContour() 2 { 3 m_contour.clear(); 4 5 //2 extra for invisible border 6 std::vector<std::vector<bool> > boolVec = 7 std::vector<std::vector<bool> >(m_bitmapDimensions.x + 2, 8 std::vector<bool>(m_bitmapDimensions.y + 2, false)); 9 10 //lock the bitmap 11 ALLEGRO_LOCKED_REGION* region; 12 region = al_lock_bitmap 13 (m_bitmap, 14 ALLEGRO_PIXEL_FORMAT_ABGR_8888, 15 ALLEGRO_LOCK_READONLY); 16 17 m_floodQ.push(b2Vec2(-1,-1)); 18 19 //flood fill 20 while (!m_floodQ.empty()) 21 { 22 b2Vec2 vert = m_floodQ.front(); 23 m_floodQ.pop(); 24 25 //no going past the 1px invisible border 26 if(boolVec[vert.x + 1][vert.y + 1]) 27 { 28 continue; 29 } 30 31 if(vert.x >= 0 && vert.y >= 0 && 32 vert.x < m_bitmapDimensions.x && 33 vert.y < m_bitmapDimensions.y) 34 { 35 unsigned char *row = (unsigned char*)region->data; 36 row += (int)vert.y * region->pitch; 37 uint32_t *pixel = (unsigned int*)row + (int)vert.x; 38 int alpha = *pixel >> 24; 39 //add pixel if alpha matches 40 if(alpha >= m_alpha) 41 { 42 m_contour.push_back(b2Vec2((vert.x - (m_bitmapDimensions.x / 2)) , 43 ( vert.y - (m_bitmapDimensions.y / 2)))); 44 continue; 45 } 46 47 } 48 49 boolVec[vert.x + 1][vert.y + 1] = true; 50 51 //iterate the 8 corners 52 for(int i = -1; i < 2; ++i) 53 { 54 for(int j = -1; j < 2; ++j) 55 { 56 //do not iterate yourself 57 if(i == 0 && j == 0) 58 { 59 continue; 60 } 61 62 b2Vec2 curVert = vert; 63 curVert.x += i; 64 curVert.y += j; 65 66 //no going past 1px invisible border 67 if(curVert.x < -1 || curVert.y < -1 68 || curVert.x > m_bitmapDimensions.x 69 || curVert.y > m_bitmapDimensions.y) 70 { 71 continue; 72 } 73 //if it has not been processed, process the pixel 74 if(!boolVec[curVert.x + 1][curVert.y + 1]) 75 { 76 m_floodQ.push(b2Vec2(curVert.x,curVert.y)); 77 } 78 79 } 80 } 81 } 82 83 al_unlock_bitmap(m_bitmap); 84 }

Basically you lock it.
Then do:

       unsigned char *row = (unsigned char*)region->data;
        row += (int)YOUR_Y_COORDINATE_HERE * region->pitch;
        uint32_t *pixel = (unsigned int*)row + (int)YOUR_X_COORDINATE_HERE;
        int alpha = *pixel >> 24;

Edgar Reynaldo
Member #8,592
May 2007
avatar

alehbeer
Member #12,996
July 2011
avatar

A5

No God Mode Required
Member #7,195
May 2006

What about using this to check if a pixel is transparent: https://www.allegro.cc/forums/thread/608076/927864 ?

Mark Oates
Member #1,146
March 2001
avatar

This takes an image, pulls the top left color, and draws a green rectangle showing trim region that is made of up that color.

#SelectExpand
1 2void show_trim_region(ALLEGRO_BITMAP *bmp) 3{ 4 int top_most = al_get_bitmap_height(bmp); 5 int right_most = 0; 6 int bottom_most = 0; 7 int left_most = al_get_bitmap_width(bmp); 8 9 al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE); 10 11 ALLEGRO_COLOR top_left_color = al_get_pixel(bmp, 0, 0); 12 for (int y=0; y<al_get_bitmap_height(bmp); y++) 13 for (int x=0; x<al_get_bitmap_width(bmp); x++) 14 { 15 ALLEGRO_COLOR this_color = al_get_pixel(bmp, x, y); 16 if (!color::basically_equal(this_color, top_left_color)) 17 { 18 if (x < left_most) left_most = x; 19 if (y < top_most) top_most = y; 20 if (x > right_most) right_most = x; 21 if (y < left_most) top_most = y; 22 } 23 } 24 25 al_unlock_bitmap(bmp); 26 27 28 // draw a rectangle around the trim area 29 30 ALLEGRO_STATE state; 31 al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP); 32 33 al_set_target_bitmap(bmp); 34 al_draw_rectangle(left_most, top_most, right_most, bottom_most, color::green, 1.0); 35 36 al_restore_state(&state); 37}

(You'll use this too):

namespace color
{
bool basically_equal(const ALLEGRO_COLOR &col1, const ALLEGRO_COLOR &col2, float threshold=0.0001)
{
  if (abs(col1.a - col2.a) > threshold) return false;
  if (abs(col1.g - col2.g) > threshold) return false;
  if (abs(col1.b - col2.b) > threshold) return false;
  if (abs(col1.r - col2.r) > threshold) return false;
  return true;
}
}

Go to: