数字图像处理简单APIs
学习数字图像处理有一段时间了,期间编写了许多的,API用来消化,这些算法的真正涵义。我是在Linux上使用q
3.3的开发库做为一个平台,编写了一个很简单的UI用于观察数字图像处理的结果。我的代码是C++编写的(尽管不是好的选择)。以下是我的APIs:
/********************************************************
* This is a static type of transform of image
* And here I have used BMP image for instance
* Author :Stephen Du
* ` Date :07-11-22
********************************************************/
#include
#include
#include
#include
#include "../include/bmpstruct.h"
#include "../include/newtrace.h"
#include "../include/stephentype.h"
/*
* APIs in this lib will only deal with rgb data
* given by a buffer type and anything else will not
* be here; All the image transform can be put ino practice
* through array, but too low efficiency;All the API here
* will not save a copy, so the undo will not be here
*/
using namespace std;
namespace static_transform_space{
#define VERTICAL_DIRECTION 0
#define HORIZONAL_DIRECTION 1
void mirror_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UINT32 ver_hor)
//ver_hor = 0:vertical axis mirror;=1:horizonal axis mirror
{
if(ver_hor == 1){
cRgbQuad* p = NEW_ARRAY cRgbQuad[width];
for(UINT32 i=0; i< (height%2==0?height/2:(height-1)/2); i++){
memcpy((void*)(p), (void*)(p_rgb+i*width), width*4);
memcpy((void*)(p_rgb+i*width), (void*)(p_rgb+(height-i-1)*width), width*4);
memcpy((void*)(p_rgb+(height-1-i)*width), (void*)p, width*4);
}
DEL_ARRAY(p);
}else{
const UINT32 hwidth = width%2==0 ? width/2 : (width-1) / 2;
for(UINT32 i=0; i cRgbQuad rgb;
for(UINT32 j=0; j<(width%2==0?width/2:(width-1)/2); j++){
std::swap(*(p_rgb+i*width+j), *(p_rgb+(i*width+width-j-1)));
}
}
}
return;
}
效果图:
/*
* The APIs here will do plus minus mutiple and division
* Minus contain two types -factor or factor-:" factor>0:factor - rgb" and "factor<0 rgb - abs(factor)"
* it all depends the factor by caller; And all the arith result will be 0!!
* Two divisions factor divide or divide factor!
* "type" determine arith type:plus minus...
* type=0:plus factor; user can use this to implement minus by passing minus factor
* 1:factor minus rgb, if result <0 ,0 return 0
* 2:mutiple/division "rgb*(1/factor)"; both mutiple and division here
* 3:factor/rgb implement here
*/
void red_arith_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const UINT32 type)
//factor is a special parrameter to division
//if factor<0 && type == 2!! means division
{
switch(type){
case 0:
for(UINT32 i=0; i p_rgb->rgbRed = factor + p_rgb->rgbRed > 0 && factor + p_rgb->rgbRed < 255 ?
factor + p_rgb->rgbRed : factor + p_rgb->rgbRed > 0 ? 255 : 0;
//factor<0 means minus
p_rgb++;
}
break;
case 1:
for(UINT32 i=0; i p_rgb->rgbRed = factor - p_rgb->rgbRed > 0 ? factor - p_rgb->rgbRed : 0;
p_rgb++;
}
break;
case 2:
if(factor > 0){
for(UINT32 i=0; i p_rgb->rgbRed = p_rgb->rgbRed*factor > 255 ? 255 : p_rgb->rgbRed*factor;
p_rgb++;
}
}else if(factor < 0){
for(UINT32 i=0; i p_rgb->rgbRed = p_rgb->rgbRed / (-factor);
p_rgb++;
p_rgb++;
}
}else
p_rgb->rgbRed = 255;
break;
case 3:
for(UINT32 i=0; i p_rgb->rgbRed = p_rgb->rgbRed == 0 ? 255 : factor / p_rgb->rgbRed;
p_rgb++;
}
break;
default:
break;
}
return;
}
void red_reverse_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height)
{
red_arith_trans(p_rgb, width, height, 255, 1);
return;
}
void green_arith_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const UINT32 type)
{
UINT32 total = width*height;
case 0:
while(total--){
p_rgb->rgbGreen = factor + p_rgb->rgbGreen > 0 && factor + p_rgb->rgbGreen < 255 ?
factor + p_rgb->rgbGreen :factor + p_rgb->rgbGreen > 0 ? 255 : 0;
p_rgb++;
}
break;
case 1:
while(total--){
p_rgb->rgbGreen = factor - p_rgb->rgbGreen > 0 ? factor - p_rgb->rgbGreen > 0 : 0;
p_rgb++;
}
break;
case 2:if(factor > 0){
while(total--){
p_rgb->rgbGreen = factor*p_rgb->rgbGreen > 255 ? 255 : factor*p_rgb->rgbGreen;
p_rgb++;
}
}else if(factor < 0){
while(total--){
p_rgb->rgbGreen = p_rgb->rgbGreen / (-factor);
p_rgb++;
}
}else
p_rgb->rgbGreen = 255;
break;
case 3:
while(total--){
p_rgb->rgbGreen = p_rgb->rgbGreen == 0 ? 255 : factor / p_rgb->rgbGreen;
p_rgb++;
}
break;
default:
break;
}
return;
}
void green_reverse_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height)
{
green_arith_trans(p_rgb, width, height, 255, 1);
return;
}
void blue_arith_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const UINT32 type)
{
UINT32 total = width*height;
switch(type){
case 0:
while(total--){
p_rgb->rgbBlue = factor+p_rgb->rgbBlue > 0 && factor+p_rgb->rgbBlue < 255 ?
factor+p_rgb->rgbBlue : factor+p_rgb->rgbBlue > 0 ? 255 : 0;
p_rgb++;
}
break;
case 1:
while(total--){
p_rgb->rgbBlue = factor - p_rgb->rgbBlue > 0 ? factor - p_rgb->rgbBlue : 0;
p_rgb++;
}
break;
case 2:
if(factor > 0){
while(total--){
p_rgb->rgbBlue = factor * p_rgb->rgbBlue > 255 ? 255 : factor * p_rgb->rgbBlue;
p_rgb++;
}
}else if(factor < 0){
while(total--){
p_rgb->rgbBlue = p_rgb->rgbBlue / (-factor);
p_rgb++;
}
}else
p_rgb->rgbBlue = 255;
break;
case 3:
while(total--){
while(total--){
p_rgb->rgbBlue = p_rgb->rgbBlue == 0 ? 255 : factor / p_rgb->rgbBlue;
p_rgb++;
}
break;
default:
break;
}
return;
}
void blue_reverse_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height)
{
blue_arith_trans(p_rgb, width, height, 255, 1);
return;
}
void rgb_arith_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UINT32 factor,
const UINT32 type)
{
red_arith_trans(p_rgb, width, height, factor, type);
green_arith_trans(p_rgb, width, height, factor, type);
blue_arith_trans(p_rgb, width, height, factor, type);
return;
}
void rgb_reverse_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 width,
const UINT32 height)
{
red_reverse_trans(p_rgb, width, height);
green_reverse_trans(p_rgb, width, height);
blue_reverse_trans(p_rgb, width, height);
return;
}
/*
* The following are linear transform for rgb
*/
void red_linear_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const INT32 deviation)
//result(r, g, b) = factor*(r, g, b)+deviation
{
red_arith_trans(p_rgb, width, height, factor, 2);
red_arith_trans(p_rgb, width, height, deviation, 0);
}
void green_linear_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const INT32 deviation)
//result(r, g, b) = factor*(r, g, b)+deviation
{
green_arith_trans(p_rgb, width, height, factor, 2);
green_arith_trans(p_rgb, width, height, deviation, 0);
}
}
void blue_linear_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const INT32 deviation)
//result(r, g, b) = factor*(r, g, b)+deviation
{
blue_arith_trans(p_rgb, width, height, factor, 2);
blue_arith_trans(p_rgb, width, height, deviation, 0);
}
void rgb_linear_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 factor,
const INT32 deviation)
//result(r, g, b) = factor*(r, g, b)+deviation
{
red_linear_trans(p_rgb, width, height, factor, deviation);
green_linear_trans(p_rgb, width, height, factor, deviation);
blue_linear_trans(p_rgb, width, height, factor, deviation);
}
/*
* Mapping operation can map the original rgb to the range
* of [g0, g1], but seems not so useful;
* Attention!!!These APIs has dealt factor in multiple with rgb /factor
* and if rgb==0 the map will seems as if uncorrect because of
* arith treat negative result as 0!!!
*/
void red_map_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_orig0,
cRgbQuad* p_orig1,
cRgbQuad* p_des0,
cRgbQuad* p_des1)
{
assert(p_orig0->rgbRed - p_orig1->rgbRed != 0);
const INT32 factor = (p_des1->rgbRed - p_des0->rgbRed) / (p_orig1->rgbRed - p_orig0->rgbRed);
//if factor < 0 means red / factor!!
red_arith_trans(p_rgb, width, height, -(p_orig0->rgbRed), 0);
red_arith_trans(p_rgb, width, height, factor, 2);
red_arith_trans(p_rgb, width, height, p_des0->rgbRed, 0);
return;
}
void green_map_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_orig0,
cRgbQuad* p_orig1,
cRgbQuad* p_des0,
cRgbQuad* p_des1)
{
assert(p_orig1->rgbGreen - p_orig0->rgbGreen != 0);
const INT32 factor = (p_des1->rgbGreen - p_des0->rgbGreen) / (p_orig1->rgbGreen - p_orig0->rgbGreen);
green_arith_trans(p_rgb, width, height, -p_orig0->rgbGreen, 0);
green_arith_trans(p_rgb, width, height, factor, 2);
green_arith_trans(p_rgb, width, height, p_des0->rgbGreen, 0);
return;
}
void blue_map_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_orig0,
cRgbQuad* p_orig1,
cRgbQuad* p_des0,
cRgbQuad* p_des1)
{
assert(p_orig1->rgbBlue - p_orig0->rgbBlue != 0);
const INT32 factor = (p_des1->rgbBlue - p_des0->rgbBlue) / (p_orig1->rgbBlue - p_orig0->rgbBlue);
blue_arith_trans(p_rgb, width, height, -p_orig0->rgbBlue, 0);
blue_arith_trans(p_rgb, width, height, factor, 2);
blue_arith_trans(p_rgb, width, height, p_des0->rgbBlue, 0);
return;
}
void rgb_map_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_orig0,
cRgbQuad* p_orig1,
cRgbQuad* p_des0,
cRgbQuad* p_des1)
{
red_map_trans(p_rgb, width, height, p_orig0, p_orig1, p_des0, p_des1);
green_map_trans(p_rgb, width, height, p_orig0, p_orig1, p_des0, p_des1);
blue_map_trans(p_rgb, width, height, p_orig0, p_orig1, p_des0, p_des1);
return;
}
/*
* Clip operation will cut out lowerthan f-min and higher than f-max so that the rgb data
* we care will be more clear and other blur
*/
void rgb_clip_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_min,
cRgbQuad* p_max)
{
cRgbQuad max, min;
max.rgbRed = max.rgbGreen = max.rgbBlue = 255;
min.rgbRed = min.rgbGreen = min.rgbBlue = 0;
rgb_map_trans(p_rgb, width, height, p_min, p_max, &min, &max);
}
/*
* Threshhold is a special for rgb_clip_trans, but has pleaps so
* implement differently */
void red_threshhold_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_threshhold,
cRgbQuad* p_high,
cRgbQuad* p_low)
{
for(UINT32 i=0; i if(p_rgb->rgbRed > p_threshhold->rgbRed)
p_rgb->rgbRed = p_high->rgbRed;
else
p_rgb->rgbRed = p_low->rgbRed;
p_rgb++;
}
}
void green_threshhold_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_threshhold,
cRgbQuad* p_high,
cRgbQuad* p_low)
{
for(UINT32 i=0; i if(p_rgb->rgbGreen > p_threshhold->rgbGreen)
if(p_rgb->rgbGreen > p_threshhold->rgbGreen)
p_rgb->rgbGreen = p_high->rgbGreen;
else
p_rgb->rgbGreen = p_low->rgbGreen;
p_rgb++;
}
}
void blue_threshhold_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_threshhold,
cRgbQuad* p_high,
cRgbQuad* p_low)
{
for(UINT32 i=0; i if(p_rgb->rgbBlue > p_threshhold->rgbBlue)
p_rgb->rgbBlue = p_high->rgbBlue;
else
p_rgb->rgbBlue = p_low->rgbBlue;
p_rgb++;
}
}
void rgb_threshhold_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_threshhold,
cRgbQuad* p_high,
cRgbQuad* p_low)
{
red_threshhold_trans(p_rgb, width, height, p_threshhold, p_high, p_low);
green_threshhold_trans(p_rgb, width, height, p_threshhold, p_high, p_low);
blue_threshhold_trans(p_rgb, width, height, p_threshhold, p_high, p_low);
return;
}
/*
* The upwared APIs are linear transform and the following are not!
*/
void red_log_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UINT32 type)
//This is a mutifunction API for log(10)(rgb) and 10^(rgb) and other unlinear transform
//type=0:log;1:10^rgb
{
switch(type){
case 0: //log operation
for(UINT32 i=0; i p_rgb->rgbRed = (UCHAR8)logl((LONG32)(p_rgb->rgbRed+1));
p_rgb++;
}
break;
case 1:
for(UINT32 i=0; i p_rgb->rgbRed = (UINT32)powl(10, (LONG32)p_rgb->rgbRed);
p_rgb++;
}
break;
}
}
/*
* This will intensity
*/
void red_intensity_level_slice(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_min,
cRgbQuad* p_max,
const UINT32 type)
//type =0:[fmin, fmax]kept;type=1:[0,fmin][fmax, 255]kept
{
if(type == 0){
for(UINT32 i=0; i if(p_rgb->rgbRed >= p_max->rgbRed || p_rgb->rgbRed <= p_min->rgbRed){
p_rgb->rgbRed = 0;
}
p_rgb++;
}
}else{
for(UINT32 i=0; i if(p_rgb->rgbRed <= p_max->rgbRed && p_rgb->rgbRed >= p_min->rgbRed){
p_rgb->rgbRed = 0;
}
p_rgb++;
}
}
return;
}
void green_intensity_level_slice(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_min,
cRgbQuad* p_max,
const UINT32 type)
{
if(type == 0){
for(UINT32 i=0; i< width*height; i++){
for(UINT32 i=0; i< width*height; i++){
if(p_rgb->rgbGreen >= p_max->rgbGreen || p_rgb->rgbGreen <= p_min->rgbGreen){
p_rgb->rgbGreen = 0;
}
p_rgb++;
}
}else{
for(UINT32 i=0; i< width*height; i++){
if(p_rgb->rgbGreen <= p_max->rgbGreen && p_rgb->rgbGreen >= p_min->rgbGreen){
p_rgb->rgbGreen = 0;
}
p_rgb++;
}
}
return;
}
void blue_intensity_level_slice(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_min,
cRgbQuad* p_max,
const UINT32 type)
{
if(type == 0){
for(UINT32 i=0; i< width*height; i++){
if(p_rgb->rgbBlue >= p_max->rgbBlue || p_rgb->rgbBlue <= p_min->rgbBlue){
p_rgb->rgbBlue = 0;
}
p_rgb++;
}
}else{
for(UINT32 i=0; i< width*height; i++){
if(p_rgb->rgbBlue <= p_max->rgbBlue && p_rgb->rgbBlue >= p_min->rgbBlue){
p_rgb->rgbBlue = 0;
}
p_rgb++;
}
}
return;
}
void rgb_intensity_level_slice(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
cRgbQuad* p_min,
cRgbQuad* p_max,
const UINT32 type)
{
red_intensity_level_slice(p_rgb, width, height, p_min, p_max, type);
green_intensity_level_slice(p_rgb, width, height, p_min, p_max, type);
blue_intensity_level_slice(p_rgb, width, height, p_min, p_max, type);
return;
}
/*
* Histogram is used to increase the most frequency gray level
*/
void red_histogram_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UCHAR8* p_histogram)
{
const UCHAR8 d = 255 / (width*height);
UCHAR8 c[256];
c[0] = d*p_histogram[0];
for(UINT32 i=1; i != 256; i++){
c[i] = c[i-1] + p_histogram[i]*d;
}
for(UINT32 i=0; i != width*height; i++){
p_rgb->rgbRed = c[p_rgb->rgbRed];
p_rgb++;
}
return;
}
void green_histogram_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UCHAR8* p_histogram)
{
UCHAR8 d = 255 / (width*height);
UCHAR8 c[256];
c[0] = d*p_histogram[0];
for(UINT32 i=1; i != 256; i++){
c[i] = c[i-1]+ p_histogram[i]*d;
}
for(UINT32 i=0; i != width*height; i++){
p_rgb->rgbGreen = c[p_rgb->rgbGreen];
p_rgb++;
}
return;
}
void blue_histogram_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UCHAR8* p_histogram)
{
UCHAR8 d = 255 / (width*height);
UCHAR8 c[256];
c[0] = d*p_histogram[0];
for(UINT32 i=1; i != 256; i++){
c[i] = c[i-1]+ p_histogram[i]*d;
}
for(UINT32 i=0; i != width*height; i++){
p_rgb->rgbBlue = c[p_rgb->rgbBlue];
p_rgb++;
}
return;
}
void rgb_histogram_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const UCHAR8* p_histogram)
{
red_histogram_trans(p_rgb, width, height, p_histogram);
green_histogram_trans(p_rgb, width, height, p_histogram);
blue_histogram_trans(p_rgb, width, height, p_histogram);
}
/*
* This is a most important operation!convolution
*/
void shift_trans(cRgbQuad* p_rgb,
const UINT32 width,
const UINT32 height,
const INT32 shift,
const UINT32 ver_hor,
const UINT32 cycle)
//ver_hor = 0:vertically shift ;1:horizontally shift
//if shit < 0 up/left else down/right
//cycle = 1 :shift in a cycle way;0:fill with black color
{
switch(ver_hor){
case VERTICAL_DIRECTION:
if(shift > 0){
if(cycle == 0){
#if 0
for(UINT32 i=0; i memcpy((void*)(p_rgb+width*(height-1-i)),
(void*)(p_rgb+(height-shift-i-1)*width), width*4);
}
#endif
memmove((void*)(p_rgb+width*(shift)), (void*)(p_rgb), (height-shift)*width*4);
memset((void*)(p_rgb), 0, shift*width*4);
}else{
cRgbQuad* p = NEW_ARRAY cRgbQuad[width*shift];
//It seems as if the memory used here is too munch!
memcpy((void*)(p), (void*)(p_rgb+(height-shift)*width),
shift*width*4);
memmove((void*)(p_rgb+shift*width), (void*)(p_rgb),
(height-shift)*width*4);
memcpy((void*)(p_rgb), (void*)(p), shift*width*4);
DEL_ARRAY(p);
}
}else{
#if 0
for(UINT32 i=0; i memcpy((void*)(p_rgb+i*width), (void*)(p_rgb+(i-shift)*width), width*4);
}
#endif
if(cycle == 0){
memmove((void*)(p_rgb), (void*)(p_rgb+width*(-shift)),
(height+shift)*width*4);
memset((void*)(p_rgb+(height+shift)*width), 0, (-shift)*width*4);
//The black color will fill the lower lines
}else{
shift_trans(p_rgb, width, height, height+shift, ver_hor, cycle);
//A lot memory wasted here but waste time to me to use a recursive!
}
}
break;
case HORIZONAL_DIRECTION:
if(shift > 0){
if(cycle == 0){
for(UINT32 i=0; i memmove((void*)(p_rgb+i*width+shift),
(void*)(p_rgb+i*width),
(width-shift)*4);
memset((void*)(p_rgb+i*width), 0, shift*4);
}
}else{
cRgbQuad* p = NEW_ARRAY cRgbQuad[shift];
for(UINT32 i=0; i memcpy((void*)(p), (void*)(p_rgb+i*width+width-shift),
shift*4);
memmove((void*)(p_rgb+i*width+shift),
(void*)(p_rgb+i*width),
(void*)(p_rgb+i*width),
(width-shift)*4);
memcpy((void*)(p_rgb+i*width), (void*)(p), shift*4);
}
DEL_ARRAY(p);
}
}else{
if(cycle == 0){
for(UINT32 i=0; i memmove((void*)(p_rgb+i*width), (void*)(p_rgb+i*width-shift), (width+shift)*4);
memset((void*)(p_rgb+i*width+width+shift), 0, -shift*4);
}
}else{
shift_trans(p_rgb, width, height, height+shift, ver_hor, cycle);
}
}
break;
default:
break;
}
}
} //static_transform_space
namespace stat_trans_space = static_transform_space;
阅读(1533) | 评论(0) | 转发(0) |