GIMP源程序:
static void
remove_redeye (GimpDrawable *drawable)
{
GimpPixelRgn src_rgn;
GimpPixelRgn dest_rgn;
gint progress, max_progress;
gboolean has_alpha;
gint x, y;
gint width, height;
gint i;
gpointer pr;
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
&x, &y, &width, &height))
return;
gimp_progress_init (_("Removing red eye"));
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
progress = 0;
max_progress = width * height;
gimp_pixel_rgn_init (&src_rgn, drawable,
x, y, width, height, FALSE, FALSE);
gimp_pixel_rgn_init (&dest_rgn, drawable,
x, y, width, height, TRUE, TRUE);
for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), i = 0;
pr != NULL;
pr = gimp_pixel_rgns_process (pr), i++)
{
redeye_inner_loop (src_rgn.data, dest_rgn.data, src_rgn.w, src_rgn.h,
src_rgn.bpp, has_alpha, src_rgn.rowstride);
progress += src_rgn.w * src_rgn.h;
if (i % 16 == 0)
gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
}
gimp_progress_update (1.0);
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
gimp_drawable_update (drawable->drawable_id, x, y, width, height);
}
主要功能在redeye_inner_loop这个函数里,这个函数里面要改两处:
1 把gint之类改成int
2 原程序是按r,g,b,a来处理的,实际要反过来,也就是说,
const gint red = 0;
const gint green = 1;
const gint blue = 2;
const gint alpha = 3;
倒序就可以了。程序里实际操作的图都是24位真彩,没有用到a,所以改成了:
const int red = 2;
const int green = 1;
const int blue = 0;
const int alpha = 3;//没有用到
主要改造
remove_redeye 这个函数。说改造,其实就是按范围取值计算而已。
简单改写之写:
#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
void remove_redeye()
{
if (!m_image.isValid())
return;
//准备数据
int bytes = m_image.getBitsPerPixel()/8;
bool has_alpha = m_image.isTransparent();
fipWinImage image2 = m_image;
int x = 0;
int y = 0;
int width = m_image.getWidth();
int height = m_image.getHeight();
int size = width*height*3;
size = WIDTHBYTES(m_image.getBitsPerPixel()*width)*height;
BITMAPINFO* info = m_image.getInfo();
int rowstride = WIDTHBYTES(m_image.getBitsPerPixel()*width);
BYTE *src_ptr = m_image.accessPixels();
BYTE *dest_ptr = new BYTE[size];
BYTE* dest_line = dest_ptr;
redeye_inner_loop(src_ptr, dest_ptr, width, height, bytes, has_alpha, rowstride);
char* szFile = "out.bmp";
g_fSaveDataToBitmap(&(info->bmiHeader), szFile, dest_ptr, m_image.getImageSize());
m_imageDest.load(szFile);
if (!m_imageDest.isValid())
{
AfxMessageBox("处理失败!");
}
delete[] dest_ptr;
}
程序使用freeimage读出源图,处理完保存成bmp。注意,一定要用WIDTHBYTES保证字节对齐。