|
Toshihiro Shimizu |
890ddd |
#include <string></string>
|
|
Toshihiro Shimizu |
890ddd |
#include <vector></vector>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdexcept></stdexcept>
|
|
Toshihiro Shimizu |
890ddd |
#include <fstream></fstream>
|
|
Toshihiro Shimizu |
890ddd |
#include <limits></limits>
|
|
Toshihiro Shimizu |
890ddd |
#include <cmath></cmath>
|
|
Toshihiro Shimizu |
890ddd |
#include "igs_ifx_common.h" /* igs::image::rgba */
|
|
Toshihiro Shimizu |
890ddd |
#include "igs_gaussian_blur.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "igs_gauss_distribution.cpp"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Shinya Kitaoka |
120a6e |
const int diameter_from_radius_(const int radius) {
|
|
Shinya Kitaoka |
120a6e |
/* テーブルの半径サイズ(=中心位置)からテーブルの大きさを決める */
|
|
Shinya Kitaoka |
120a6e |
return radius * 2 + 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class rt=""></class>
|
|
Toshihiro Shimizu |
890ddd |
void blur_1st_hori_(
|
|
Shinya Kitaoka |
120a6e |
const double **in_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int height_with_margin, const int width_with_margin,
|
|
Shinya Kitaoka |
120a6e |
double *brush_sequence // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int int_radius,
|
|
Shinya Kitaoka |
120a6e |
double **out_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 参照画像用情報(no margin) */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int ref_channels, const double real_radius, const double sigma) {
|
|
Shinya Kitaoka |
120a6e |
const int brush_diameter = diameter_from_radius_(int_radius);
|
|
Shinya Kitaoka |
120a6e |
const int width_no_margin = width_with_margin - int_radius * 2;
|
|
Shinya Kitaoka |
120a6e |
const int r_max = std::numeric_limits<rt>::max();</rt>
|
|
Shinya Kitaoka |
120a6e |
const RT *ref_vert = ref;
|
|
Shinya Kitaoka |
120a6e |
const RT *ref_hori = ref;
|
|
Shinya Kitaoka |
120a6e |
double before_real_radius = -1.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 縦方向 */
|
|
Shinya Kitaoka |
120a6e |
for (int yo = 0; yo < height_with_margin; ++yo) {
|
|
Shinya Kitaoka |
120a6e |
if (ref != 0) {
|
|
Shinya Kitaoka |
120a6e |
if (int_radius < yo && yo < (height_with_margin - int_radius)) {
|
|
Shinya Kitaoka |
120a6e |
ref_vert += width_no_margin * ref_channels;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ref_hori = ref_vert;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 横方向 */
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
|
|
Shinya Kitaoka |
120a6e |
if (ref != 0) {
|
|
Shinya Kitaoka |
120a6e |
const double read_r =
|
|
Shinya Kitaoka |
120a6e |
real_radius *
|
|
Shinya Kitaoka |
120a6e |
igs::color::ref_value(ref_hori, ref_channels, r_max, ref_mode);
|
|
Shinya Kitaoka |
120a6e |
ref_hori += ref_channels;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (read_r != before_real_radius) {
|
|
Shinya Kitaoka |
120a6e |
gauss_distribution_1d_(brush_sequence, brush_diameter,
|
|
Shinya Kitaoka |
120a6e |
igs::gaussian_blur_hv::int_radius(read_r),
|
|
Shinya Kitaoka |
120a6e |
read_r, sigma);
|
|
Shinya Kitaoka |
120a6e |
before_real_radius = read_r;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* ガウス分布で横blur */
|
|
Shinya Kitaoka |
120a6e |
double accum = 0;
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
for (int xb=0, xi=xx; xb
|
|
Shinya Kitaoka |
120a6e |
accum += in_plane_with_margin[yo][xi] * brush_sequence[xb];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
const double *bru_seq = brush_sequence;
|
|
Shinya Kitaoka |
120a6e |
int bru_dia = brush_diameter;
|
|
Shinya Kitaoka |
120a6e |
const double *inn_pla = &in_plane_with_margin[yo][xx];
|
|
Shinya Kitaoka |
120a6e |
while (0 < bru_dia--) {
|
|
Shinya Kitaoka |
120a6e |
accum += (*inn_pla++) * (*bru_seq++);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
out_plane_with_margin[yo][xo] = accum;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void blur_1st_hori_(
|
|
shun-iwasawa |
481b59 |
const double** in_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const int height_with_margin, const int width_with_margin,
|
|
shun-iwasawa |
481b59 |
double* brush_sequence // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const int int_radius,
|
|
shun-iwasawa |
481b59 |
double** out_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 参照画像用情報(no margin) */
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const float* ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const double real_radius, const double sigma) {
|
|
shun-iwasawa |
481b59 |
const int brush_diameter = diameter_from_radius_(int_radius);
|
|
shun-iwasawa |
481b59 |
const int width_no_margin = width_with_margin - int_radius * 2;
|
|
shun-iwasawa |
481b59 |
// const int r_max = std::numeric_limits<rt>::max();</rt>
|
|
shun-iwasawa |
481b59 |
const float* ref_vert = ref;
|
|
shun-iwasawa |
481b59 |
const float* ref_hori = ref;
|
|
shun-iwasawa |
481b59 |
double before_real_radius = -1.0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 縦方向 */
|
|
shun-iwasawa |
481b59 |
for (int yo = 0; yo < height_with_margin; ++yo) {
|
|
shun-iwasawa |
481b59 |
if (ref != nullptr) {
|
|
shun-iwasawa |
481b59 |
if (int_radius < yo && yo < (height_with_margin - int_radius)) {
|
|
shun-iwasawa |
481b59 |
ref_vert += width_no_margin;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
ref_hori = ref_vert;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 横方向 */
|
|
shun-iwasawa |
481b59 |
for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
|
|
shun-iwasawa |
481b59 |
if (ref != 0) {
|
|
shun-iwasawa |
481b59 |
const double read_r = real_radius * (*ref_hori);
|
|
shun-iwasawa |
481b59 |
ref_hori++;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (read_r != before_real_radius) {
|
|
shun-iwasawa |
481b59 |
gauss_distribution_1d_(brush_sequence, brush_diameter,
|
|
shun-iwasawa |
481b59 |
igs::gaussian_blur_hv::int_radius(read_r),
|
|
shun-iwasawa |
481b59 |
read_r, sigma);
|
|
shun-iwasawa |
481b59 |
before_real_radius = read_r;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
/* ガウス分布で横blur */
|
|
shun-iwasawa |
481b59 |
double accum = 0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
const double* bru_seq = brush_sequence;
|
|
shun-iwasawa |
481b59 |
int bru_dia = brush_diameter;
|
|
shun-iwasawa |
481b59 |
const double* inn_pla = &in_plane_with_margin[yo][xx];
|
|
shun-iwasawa |
481b59 |
while (0 < bru_dia--) {
|
|
shun-iwasawa |
481b59 |
accum += (*inn_pla++) * (*bru_seq++);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
out_plane_with_margin[yo][xo] = accum;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class rt=""></class>
|
|
Toshihiro Shimizu |
890ddd |
void blur_2nd_vert_(
|
|
Shinya Kitaoka |
120a6e |
const double **in_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int height_with_margin, const int width_with_margin,
|
|
Shinya Kitaoka |
120a6e |
double *brush_sequence // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int int_radius,
|
|
Shinya Kitaoka |
120a6e |
double **out_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 参照画像用情報(no margin) */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int ref_channels, const double real_radius, const double sigma) {
|
|
Shinya Kitaoka |
120a6e |
const int brush_diameter = diameter_from_radius_(int_radius);
|
|
Shinya Kitaoka |
120a6e |
const int height_no_margin = height_with_margin - int_radius * 2;
|
|
Shinya Kitaoka |
120a6e |
const int width_no_margin = width_with_margin - int_radius * 2;
|
|
Shinya Kitaoka |
120a6e |
const int r_max = std::numeric_limits<rt>::max();</rt>
|
|
Shinya Kitaoka |
120a6e |
const RT *ref_vert = ref;
|
|
Shinya Kitaoka |
120a6e |
const RT *ref_hori = ref;
|
|
Shinya Kitaoka |
120a6e |
double before_real_radius = -1.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 左右マージン部分はもう処理しなくていい */
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 横方向 */
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
|
|
Shinya Kitaoka |
120a6e |
if (ref != 0) {
|
|
Shinya Kitaoka |
120a6e |
ref_hori += ref_channels;
|
|
Shinya Kitaoka |
120a6e |
ref_vert = ref_hori;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 縦方向 */
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0, yo = int_radius; yy < height_no_margin; ++yy, ++yo) {
|
|
Shinya Kitaoka |
120a6e |
if (ref != 0) {
|
|
Shinya Kitaoka |
120a6e |
const double read_r =
|
|
Shinya Kitaoka |
120a6e |
real_radius *
|
|
Shinya Kitaoka |
120a6e |
igs::color::ref_value(ref_vert, ref_channels, r_max, ref_mode);
|
|
Shinya Kitaoka |
120a6e |
ref_vert += width_no_margin * ref_channels;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (read_r != before_real_radius) {
|
|
Shinya Kitaoka |
120a6e |
gauss_distribution_1d_(brush_sequence, brush_diameter,
|
|
Shinya Kitaoka |
120a6e |
igs::gaussian_blur_hv::int_radius(read_r),
|
|
Shinya Kitaoka |
120a6e |
read_r, sigma);
|
|
Shinya Kitaoka |
120a6e |
before_real_radius = read_r;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* ガウス分布で横blur */
|
|
Shinya Kitaoka |
120a6e |
double accum = 0;
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
for (int yb=0,yi=yy; yb
|
|
Shinya Kitaoka |
120a6e |
accum += in_plane_with_margin[yi][xo] * brush_sequence[yb];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
const double *bru_seq = brush_sequence;
|
|
Shinya Kitaoka |
120a6e |
int bru_dia = brush_diameter;
|
|
Shinya Kitaoka |
120a6e |
const double *inn_pla = &in_plane_with_margin[yy][xo];
|
|
Shinya Kitaoka |
120a6e |
while (0 < bru_dia--) {
|
|
Shinya Kitaoka |
120a6e |
accum += (*inn_pla) * (*bru_seq++);
|
|
Shinya Kitaoka |
120a6e |
inn_pla += width_with_margin;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
out_plane_with_margin[yo][xo] = accum;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void blur_2nd_vert_(
|
|
shun-iwasawa |
481b59 |
const double** in_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const int height_with_margin, const int width_with_margin,
|
|
shun-iwasawa |
481b59 |
double* brush_sequence // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const int int_radius,
|
|
shun-iwasawa |
481b59 |
double** out_plane_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 参照画像用情報(no margin) */
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const float* ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
shun-iwasawa |
481b59 |
,
|
|
shun-iwasawa |
481b59 |
const double real_radius, const double sigma) {
|
|
shun-iwasawa |
481b59 |
const int brush_diameter = diameter_from_radius_(int_radius);
|
|
shun-iwasawa |
481b59 |
const int height_no_margin = height_with_margin - int_radius * 2;
|
|
shun-iwasawa |
481b59 |
const int width_no_margin = width_with_margin - int_radius * 2;
|
|
shun-iwasawa |
481b59 |
// const int r_max = std::numeric_limits<rt>::max();</rt>
|
|
shun-iwasawa |
481b59 |
const float* ref_vert = ref;
|
|
shun-iwasawa |
481b59 |
const float* ref_hori = ref;
|
|
shun-iwasawa |
481b59 |
double before_real_radius = -1.0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 左右マージン部分はもう処理しなくていい */
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 横方向 */
|
|
shun-iwasawa |
481b59 |
for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
|
|
shun-iwasawa |
481b59 |
if (ref != nullptr) {
|
|
shun-iwasawa |
481b59 |
ref_hori++;
|
|
shun-iwasawa |
481b59 |
ref_vert = ref_hori;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/* 縦方向 */
|
|
shun-iwasawa |
481b59 |
for (int yy = 0, yo = int_radius; yy < height_no_margin; ++yy, ++yo) {
|
|
shun-iwasawa |
481b59 |
if (ref != 0) {
|
|
shun-iwasawa |
481b59 |
const double read_r = real_radius * (*ref_vert);
|
|
shun-iwasawa |
481b59 |
ref_vert += width_no_margin;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (read_r != before_real_radius) {
|
|
shun-iwasawa |
481b59 |
gauss_distribution_1d_(brush_sequence, brush_diameter,
|
|
shun-iwasawa |
481b59 |
igs::gaussian_blur_hv::int_radius(read_r),
|
|
shun-iwasawa |
481b59 |
read_r, sigma);
|
|
shun-iwasawa |
481b59 |
before_real_radius = read_r;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
/* ガウス分布で横blur */
|
|
shun-iwasawa |
481b59 |
double accum = 0;
|
|
shun-iwasawa |
481b59 |
const double* bru_seq = brush_sequence;
|
|
shun-iwasawa |
481b59 |
int bru_dia = brush_diameter;
|
|
shun-iwasawa |
481b59 |
const double* inn_pla = &in_plane_with_margin[yy][xo];
|
|
shun-iwasawa |
481b59 |
while (0 < bru_dia--) {
|
|
shun-iwasawa |
481b59 |
accum += (*inn_pla) * (*bru_seq++);
|
|
shun-iwasawa |
481b59 |
inn_pla += width_with_margin;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
out_plane_with_margin[yo][xo] = accum;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Shinya Kitaoka |
120a6e |
void get_(const T *in, const int height, const int width, const int channels,
|
|
Shinya Kitaoka |
120a6e |
const int current_ch, double **out // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
) {
|
|
Shinya Kitaoka |
120a6e |
in += current_ch;
|
|
Shinya Kitaoka |
120a6e |
const double maxi = static_cast<double>(std::numeric_limits<t>::max());</t></double>
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < height; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < width; ++xx) {
|
|
Shinya Kitaoka |
120a6e |
out[yy][xx] = static_cast<double>(*in) / maxi;</double>
|
|
Shinya Kitaoka |
120a6e |
in += channels;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void get_(const float* in, const int height, const int width,
|
|
shun-iwasawa |
481b59 |
const int channels, const int current_ch,
|
|
shun-iwasawa |
481b59 |
double** out // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
) {
|
|
shun-iwasawa |
481b59 |
in += current_ch;
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < height; ++yy) {
|
|
shun-iwasawa |
481b59 |
for (int xx = 0; xx < width; ++xx) {
|
|
shun-iwasawa |
481b59 |
out[yy][xx] = static_cast<double>(*in);</double>
|
|
shun-iwasawa |
481b59 |
in += channels;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Toshihiro Shimizu |
890ddd |
void put_margin_(
|
|
Shinya Kitaoka |
120a6e |
const double **in_with_margin // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int height_with_margin, const int width_with_margin,
|
|
Shinya Kitaoka |
120a6e |
const int channels, const int current_ch, const int margin,
|
|
Shinya Kitaoka |
120a6e |
T *out_no_margin) {
|
|
Shinya Kitaoka |
120a6e |
out_no_margin += current_ch;
|
|
Shinya Kitaoka |
120a6e |
const double maxi =
|
|
Shinya Kitaoka |
120a6e |
static_cast<double>(std::numeric_limits<t>::max()) + 0.999999;</t></double>
|
|
Shinya Kitaoka |
120a6e |
for (int yy = margin; yy < (height_with_margin - margin); ++yy) {
|
|
Shinya Kitaoka |
120a6e |
for (int xx = margin; xx < (width_with_margin - margin); ++xx) {
|
|
Shinya Kitaoka |
120a6e |
*out_no_margin = static_cast<t>(in_with_margin[yy][xx] * maxi);</t>
|
|
Shinya Kitaoka |
120a6e |
out_no_margin += channels;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void put_margin_(
|
|
shun-iwasawa |
481b59 |
const double** in_with_margin, // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
const int height_with_margin, const int width_with_margin,
|
|
shun-iwasawa |
481b59 |
const int channels, const int current_ch, const int margin,
|
|
shun-iwasawa |
481b59 |
float* out_no_margin) {
|
|
shun-iwasawa |
481b59 |
out_no_margin += current_ch;
|
|
shun-iwasawa |
481b59 |
for (int yy = margin; yy < (height_with_margin - margin); ++yy) {
|
|
shun-iwasawa |
481b59 |
for (int xx = margin; xx < (width_with_margin - margin); ++xx) {
|
|
shun-iwasawa |
481b59 |
*out_no_margin = in_with_margin[yy][xx];
|
|
shun-iwasawa |
481b59 |
out_no_margin += channels;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Shinya Kitaoka |
120a6e |
bool diff_between_channel_(const T *in, const int height, const int width,
|
|
Shinya Kitaoka |
120a6e |
const int channels, const int ch1, const int ch2) {
|
|
Shinya Kitaoka |
120a6e |
// if (ch1 == ch2) { return false; }
|
|
Shinya Kitaoka |
120a6e |
// if (channels <= ch1) { return false; }
|
|
Shinya Kitaoka |
120a6e |
// if (channels <= ch2) { return false; }
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < height; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < width; ++xx) {
|
|
Shinya Kitaoka |
120a6e |
if (in[ch1] != in[ch2]) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
in += channels;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
bool diff_between_channel_(const float* in, const int height, const int width,
|
|
shun-iwasawa |
481b59 |
const int channels, const int ch1, const int ch2) {
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < height; ++yy) {
|
|
shun-iwasawa |
481b59 |
for (int xx = 0; xx < width; ++xx) {
|
|
shun-iwasawa |
481b59 |
if (in[ch1] != in[ch2]) {
|
|
shun-iwasawa |
481b59 |
return true;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
in += channels;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
return false;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" it,="" rt=""></class>
|
|
Shinya Kitaoka |
120a6e |
void convert_hv_(const IT *in_with_margin, IT *out_no_margin,
|
|
Shinya Kitaoka |
120a6e |
const int height_with_margin, const int width_with_margin,
|
|
Shinya Kitaoka |
120a6e |
const int channels
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
double *filter // (double *)(&filter_buf.at(0))
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int int_radius,
|
|
Shinya Kitaoka |
120a6e |
double **buffer_inn // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
double **buffer_out // &(std::vector<double *="">).at(0)</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 参照画像用情報(no margin) */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
const double real_radius, const double sigma) {
|
|
Shinya Kitaoka |
120a6e |
bool diff_sw = true; /* 1番目の画像は処理する */
|
|
Shinya Kitaoka |
120a6e |
for (int cc = 0; cc < channels; ++cc) {
|
|
Shinya Kitaoka |
120a6e |
if (0 < cc) { /* 2番目のチャンネル以後 */
|
|
Shinya Kitaoka |
120a6e |
/* 1つ前のチャンネルと違いを調べる */
|
|
Shinya Kitaoka |
120a6e |
diff_sw = diff_between_channel_(in_with_margin, height_with_margin,
|
|
Shinya Kitaoka |
120a6e |
width_with_margin, channels, cc - 1, cc);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* 一つ前と同じ画像なら処理せず使い回して高速化する */
|
|
Shinya Kitaoka |
120a6e |
if (diff_sw) {
|
|
Shinya Kitaoka |
120a6e |
get_(in_with_margin, height_with_margin, width_with_margin, channels, cc,
|
|
Shinya Kitaoka |
120a6e |
buffer_inn);
|
|
Shinya Kitaoka |
120a6e |
blur_1st_hori_((const double **)(buffer_inn), height_with_margin,
|
|
Shinya Kitaoka |
120a6e |
width_with_margin, filter, int_radius, buffer_out
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
ref, ref_mode, channels, real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
blur_2nd_vert_((const double **)(buffer_out), height_with_margin,
|
|
Shinya Kitaoka |
120a6e |
width_with_margin, filter, int_radius, buffer_inn
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
ref, ref_mode, channels, real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
put_margin_((const double **)(buffer_inn), height_with_margin,
|
|
Shinya Kitaoka |
120a6e |
width_with_margin, channels, cc, int_radius, out_no_margin);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
#endif
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void convert_hv_(
|
|
shun-iwasawa |
481b59 |
const float* in_with_margin, float* out_no_margin,
|
|
shun-iwasawa |
481b59 |
const int height_with_margin, const int width_with_margin,
|
|
shun-iwasawa |
481b59 |
const int channels,
|
|
shun-iwasawa |
481b59 |
double* filter, // (double *)(&filter_buf.at(0))
|
|
shun-iwasawa |
481b59 |
const int int_radius,
|
|
shun-iwasawa |
481b59 |
double** buffer_inn, // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
double** buffer_out, // &(std::vector<double *="">).at(0)</double>
|
|
shun-iwasawa |
481b59 |
/* 参照画像用情報(no margin) */
|
|
shun-iwasawa |
481b59 |
const float* ref, /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
|
|
shun-iwasawa |
481b59 |
const double real_radius, const double sigma) {
|
|
shun-iwasawa |
481b59 |
bool diff_sw = true; /* 1番目の画像は処理する */
|
|
shun-iwasawa |
481b59 |
for (int cc = 0; cc < channels; ++cc) {
|
|
shun-iwasawa |
481b59 |
if (0 < cc) { /* 2番目のチャンネル以後 */
|
|
shun-iwasawa |
481b59 |
/* 1つ前のチャンネルと違いを調べる */
|
|
shun-iwasawa |
481b59 |
diff_sw = diff_between_channel_(in_with_margin, height_with_margin,
|
|
shun-iwasawa |
481b59 |
width_with_margin, channels, cc - 1, cc);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
/* 一つ前と同じ画像なら処理せず使い回して高速化する */
|
|
shun-iwasawa |
481b59 |
if (diff_sw) {
|
|
shun-iwasawa |
481b59 |
get_(in_with_margin, height_with_margin, width_with_margin, channels, cc,
|
|
shun-iwasawa |
481b59 |
buffer_inn);
|
|
shun-iwasawa |
481b59 |
blur_1st_hori_((const double**)(buffer_inn), height_with_margin,
|
|
shun-iwasawa |
481b59 |
width_with_margin, filter, int_radius, buffer_out, ref,
|
|
shun-iwasawa |
481b59 |
real_radius, sigma);
|
|
shun-iwasawa |
481b59 |
blur_2nd_vert_((const double**)(buffer_out), height_with_margin,
|
|
shun-iwasawa |
481b59 |
width_with_margin, filter, int_radius, buffer_inn, ref,
|
|
shun-iwasawa |
481b59 |
real_radius, sigma);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
put_margin_((const double**)(buffer_inn), height_with_margin,
|
|
shun-iwasawa |
481b59 |
width_with_margin, channels, cc, int_radius, out_no_margin);
|
|
shun-iwasawa |
481b59 |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
} // namespace
|
|
Shinya Kitaoka |
120a6e |
const int igs::gaussian_blur_hv::int_radius(const double real_radius) {
|
|
Shinya Kitaoka |
120a6e |
/* ぼかしの半径から、pixelサイズ半径(=中心位置=margin)を決める */
|
|
Shinya Kitaoka |
120a6e |
return static_cast<int>(ceil(real_radius));</int>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
const int igs::gaussian_blur_hv::buffer_bytes(const int height_with_margin,
|
|
Shinya Kitaoka |
120a6e |
const int width_with_margin,
|
|
Shinya Kitaoka |
120a6e |
const int int_radius) {
|
|
Shinya Kitaoka |
120a6e |
const int int_diameter = diameter_from_radius_(int_radius);
|
|
Shinya Kitaoka |
120a6e |
return int_diameter * int_diameter * sizeof(double) +
|
|
Shinya Kitaoka |
120a6e |
height_with_margin * width_with_margin * sizeof(double) +
|
|
Shinya Kitaoka |
120a6e |
height_with_margin * width_with_margin * sizeof(double);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void igs::gaussian_blur_hv::convert(
|
|
Shinya Kitaoka |
120a6e |
/* 入出力画像 */
|
|
shun-iwasawa |
481b59 |
const float* in_with_margin, float* out_no_margin,
|
|
Shinya Kitaoka |
120a6e |
const int height_with_margin, const int width_with_margin,
|
|
shun-iwasawa |
481b59 |
const int channels,
|
|
Shinya Kitaoka |
120a6e |
/* Pixel毎に効果の強弱 */
|
|
shun-iwasawa |
481b59 |
const float* ref, /* 求める画像(out)と同じ高、幅、ch数 */
|
|
Shinya Kitaoka |
120a6e |
/* 計算バッファ */
|
|
shun-iwasawa |
481b59 |
void* buffer,
|
|
shun-iwasawa |
481b59 |
int buffer_bytes, // Must be igs::gaussian_blur_hv::buffer_bytes(-)
|
|
Shinya Kitaoka |
120a6e |
/* Action Geometry */
|
|
shun-iwasawa |
481b59 |
const int int_radius, // =margin
|
|
Shinya Kitaoka |
120a6e |
const double real_radius, const double sigma //= 0.25
|
|
shun-iwasawa |
481b59 |
) {
|
|
Shinya Kitaoka |
120a6e |
/* 引数チェック */
|
|
Shinya Kitaoka |
120a6e |
if (real_radius <= 0.0) {
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((igs::image::rgba::siz != channels) &&
|
|
Shinya Kitaoka |
120a6e |
(igs::image::rgb::siz != channels) && (1 != channels) /* grayscale */
|
|
shun-iwasawa |
481b59 |
) {
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error("Bad channels,Not rgba/rgb/grayscale");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* 変数の設定 */
|
|
Shinya Kitaoka |
120a6e |
const int int_diameter = diameter_from_radius_(int_radius);
|
|
shun-iwasawa |
481b59 |
double* double_buffer = static_cast<double*>(buffer);</double*>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* メモリバッファの設定 */
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> filter_buf(int_diameter);</double>
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
std::vector<double*> in_plane_with_margin_dp(height_with_margin);</double*>
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < height_with_margin; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
in_plane_with_margin_dp.at(yy) = double_buffer;
|
|
Shinya Kitaoka |
120a6e |
double_buffer += width_with_margin;
|
|
Shinya Kitaoka |
120a6e |
buffer_bytes -= width_with_margin * sizeof(double);
|
|
Shinya Kitaoka |
120a6e |
if (buffer_bytes <= 0) {
|
|
Shinya Kitaoka |
120a6e |
std::string msg("buffer_inn is empty");
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error(msg);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
std::vector<double*> out_plane_with_margin_dp(height_with_margin);</double*>
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < height_with_margin; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
out_plane_with_margin_dp.at(yy) = double_buffer;
|
|
Shinya Kitaoka |
120a6e |
double_buffer += width_with_margin;
|
|
Shinya Kitaoka |
120a6e |
buffer_bytes -= width_with_margin * sizeof(double);
|
|
Shinya Kitaoka |
120a6e |
if (buffer_bytes <= 0) {
|
|
Shinya Kitaoka |
120a6e |
std::string msg("buffer_out is empty");
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error(msg);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* filter生成 */
|
|
Shinya Kitaoka |
120a6e |
gauss_distribution_1d_(&filter_buf.at(0), int_diameter, int_radius,
|
|
Shinya Kitaoka |
120a6e |
real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
convert_hv_(in_with_margin, out_no_margin, height_with_margin,
|
|
shun-iwasawa |
481b59 |
width_with_margin, channels, &filter_buf.at(0), int_radius,
|
|
shun-iwasawa |
481b59 |
&in_plane_with_margin_dp.at(0), &out_plane_with_margin_dp.at(0),
|
|
shun-iwasawa |
481b59 |
ref, real_radius, sigma);
|
|
shun-iwasawa |
481b59 |
/*
|
|
Shinya Kitaoka |
120a6e |
if ((std::numeric_limits<unsigned char="">::digits == bits) &&</unsigned>
|
|
Shinya Kitaoka |
120a6e |
((std::numeric_limits<unsigned char="">::digits == ref_bits) ||</unsigned>
|
|
Shinya Kitaoka |
120a6e |
(0 == ref_bits))) {
|
|
Shinya Kitaoka |
120a6e |
convert_hv_(static_cast<const *="" char="" unsigned="">(in_with_margin),</const>
|
|
Shinya Kitaoka |
120a6e |
static_cast<unsigned *="" char="">(out_no_margin), height_with_margin,</unsigned>
|
|
Shinya Kitaoka |
120a6e |
width_with_margin, channels, &filter_buf.at(0), int_radius,
|
|
Shinya Kitaoka |
120a6e |
&in_plane_with_margin_dp.at(0), &out_plane_with_margin_dp.at(0)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
ref, ref_mode, real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
} else if ((std::numeric_limits<unsigned short="">::digits == bits) &&</unsigned>
|
|
Shinya Kitaoka |
120a6e |
((std::numeric_limits<unsigned char="">::digits == ref_bits) ||</unsigned>
|
|
Shinya Kitaoka |
120a6e |
(0 == ref_bits))) {
|
|
Shinya Kitaoka |
120a6e |
convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
|
|
Shinya Kitaoka |
120a6e |
static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
|
|
Shinya Kitaoka |
120a6e |
height_with_margin, width_with_margin, channels,
|
|
Shinya Kitaoka |
120a6e |
&filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
|
|
Shinya Kitaoka |
120a6e |
&out_plane_with_margin_dp.at(0)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
ref, ref_mode, real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
} else if ((std::numeric_limits<unsigned short="">::digits == bits) &&</unsigned>
|
|
Shinya Kitaoka |
120a6e |
(std::numeric_limits<unsigned short="">::digits == ref_bits)) {</unsigned>
|
|
Shinya Kitaoka |
120a6e |
convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
|
|
Shinya Kitaoka |
120a6e |
static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
|
|
Shinya Kitaoka |
120a6e |
height_with_margin, width_with_margin, channels,
|
|
Shinya Kitaoka |
120a6e |
&filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
|
|
Shinya Kitaoka |
120a6e |
&out_plane_with_margin_dp.at(0)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
reinterpret_cast<const *="" short="" unsigned="">(ref), ref_mode,</const>
|
|
Shinya Kitaoka |
120a6e |
real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
} else if ((std::numeric_limits<unsigned char="">::digits == bits) &&</unsigned>
|
|
Shinya Kitaoka |
120a6e |
(std::numeric_limits<unsigned short="">::digits == ref_bits)) {</unsigned>
|
|
Shinya Kitaoka |
120a6e |
convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
|
|
Shinya Kitaoka |
120a6e |
static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
|
|
Shinya Kitaoka |
120a6e |
height_with_margin, width_with_margin, channels,
|
|
Shinya Kitaoka |
120a6e |
&filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
|
|
Shinya Kitaoka |
120a6e |
&out_plane_with_margin_dp.at(0)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Shinya Kitaoka |
120a6e |
reinterpret_cast<const *="" char="" unsigned="">(ref), ref_mode,</const>
|
|
Shinya Kitaoka |
120a6e |
real_radius, sigma);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error("Bad bits,Not uchar/ushort");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
481b59 |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|