自己満足日記。
飽きっぽいので期待しないでください。
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
タイトル変えよう。
for(int index_y = 0; index_y < dst_h; index_y++){//ループその1
for(int index_x = 0; index_x < dst_w; index_x++){//ループその2
int yc_y = 0, yc_cb = 0, yc_cr = 0;//テンポラリ
for(int offset_y = 0; offset_y < lpd_h; offset_y++){//ループその3
for(int offset_x = 0; offset_x < lpd_w; offset_x++){//ループその4
//さぁここは何をやってるでしょうΛ||Λ
yc_y += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].y;
yc_cb += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].cb;
yc_cr += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].cr;
}//ループその4終わり
}//ループその3終わり
//総和を割るとこ
fpip->ycp_temp[index_x + index_y * max_w].y = static_cast(yc_y / (lpd_w * lpd_h));
fpip->ycp_temp[index_x + index_y * max_w].cb = static_cast(yc_cb / (lpd_w * lpd_h));
fpip->ycp_temp[index_x + index_y * max_w].cr = static_cast(yc_cr / (lpd_w * lpd_h));
}//ループその2終わり
}//ループその1終わり
ループその1と2は良いでしょう。縦と横の目的解像度分ループしますよと。
そしてそれぞれのピクセル毎の総和を一時保存する
そして問題のループその3と4。ここではlpd_w*lpd_h回のループということになります。
最内周が何回まわってくるかというとdst_w*dst_h*lpd_w*lpd_h回。並び替えるとdst_w*lpd_w*lpd_h*dst_h回。
lpdは目的解像度にかけると目的解像度と元の解像度の最大公約数になる係数なので、
縦横それぞれの最大公約数をかけた数のループ回数ということになります。
どんぐらい腐ってるかっていうとキリの悪い数でやろうものなら回数が余裕で億に届きます。
そしてループ内の問題のコードです。
fpip->ycp_edit[x + y * max_w].y
上の様に記述した場合描画領域の横x、縦yの座標の輝度が返ってくるわけです
fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].y;
であるのならば
横の座標:(index_x * lpd_w + offset_x) / lps_w
盾の座標:(index_y * lpd_h + offset_y) / lps_h
ということになります。これもイミフですが端折って説明すると、
「元の画像を拡大したものにおけるある座標に対応するリサイズ先の画像の座標」を示しています。
それでまぁこれに割り算が入っているのでひどいという。
ベンチマークになるよ。やったねたえちゃん!
いくらなんでもバカ正直にn回加算する演算をn回のループで表現するのはバカなので、
同じピクセルからは一度しか画素の情報をとってこないように書き換えた結果がしたです。
typedef const PIXEL_YC * const ro_YCP;
typedef PIXEL_YC * const rw_YCP;
for(int index_y = 0; index_y < dst_h; index_y++){
//可読性対策
const int index_lcm_y = index_y * lpd_h;
//上端下端
const int edge_top = (Lcm_h - index_lcm_y) % lps_h;
const int edge_bottom = (index_lcm_y + lpd_h) % lps_h;
//重複確認
const int divide_ratio_y = (edge_top + edge_bottom > lpd_h)?edge_top + edge_bottom:lpd_h;
//可読性対策
const int begin_edge_bottom = lpd_h - edge_bottom;
//開始地点終了地点
const int poz_edge_top = (index_lcm_y / lps_h) * max_w;
const int poz_edge_bottom = ((index_lcm_y + begin_edge_bottom) / lps_h) * max_w;
for(int index_x = 0; index_x < dst_w; index_x++){
//可読性対策
const int index_lcm_x = index_x * lpd_w;
//左端右端
const int edge_left = (Lcm_w - index_lcm_x) % lps_w;
const int edge_right = (index_lcm_x + lpd_w) % lps_w;
//重複確認はあとで。
//可読性対策
const int begin_edge_right = lpd_w - edge_right;
//開始地点終了地点
const int poz_edge_left = index_lcm_x / lps_w;
const int poz_edge_right = (index_lcm_x + begin_edge_right) / lps_w;
//piece * poz->?でintの範囲をオーバーしうるので
//どこかしらで__int64にしておくこと
__int64 yc64_y = 0, yc64_cb = 0, yc64_cr = 0;
//上段左
if(edge_left || edge_top){
const __int64 piece = edge_left * edge_top;
ro_YCP poz = src_ycp + poz_edge_left + poz_edge_top;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//上段中
if(edge_top){
const __int64 piece = lps_w * edge_top;
ro_YCP temp_poz = src_ycp + poz_edge_top;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//上段右
if(edge_right || edge_top){
const __int64 piece = edge_right * edge_top;
ro_YCP poz = src_ycp + poz_edge_right + poz_edge_top;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//中段左
if(edge_left){
const __int64 piece = edge_left * lps_h;
ro_YCP temp_poz = src_ycp + poz_edge_left;
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP poz = temp_poz + (index_lcm_y + offset_y) / lps_h * max_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//中段中
//pieceは必ず非ゼロ
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP temp_poz = src_ycp + (index_lcm_y + offset_y) / lps_h * max_w;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//中段右
if(edge_right){
const __int64 piece = edge_right * lps_h;
ro_YCP temp_poz = src_ycp + poz_edge_right;
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP poz = temp_poz + (index_lcm_y + offset_y) / lps_h * max_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//下段左
if(edge_left || edge_bottom){
const __int64 piece = edge_left * edge_bottom;
ro_YCP poz = src_ycp + poz_edge_left + poz_edge_bottom;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//下段中
if(edge_bottom){
const __int64 piece = lps_w * edge_bottom;
ro_YCP temp_poz = src_ycp + poz_edge_bottom;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//下段右
if(edge_right || edge_bottom){
const __int64 piece = edge_right * edge_bottom;
ro_YCP poz = src_ycp + poz_edge_right + poz_edge_bottom;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
rw_YCP dst = dst_ycp + index_x + index_y * max_w;
//重複確認および確定
const int divide_ratio = divide_ratio_y * ((edge_left + edge_right > lpd_w)?edge_left + edge_right : lpd_w);
//総和で割るとこ
fpip->ycp_temp[index_x + index_y * max_w].y = static_cast(yc_y / (lpd_w * lpd_h));
fpip->ycp_temp[index_x + index_y * max_w].cb = static_cast(yc_cb / (lpd_w * lpd_h));
fpip->ycp_temp[index_x + index_y * max_w].cr = static_cast(yc_cr / (lpd_w * lpd_h));
}
}
コードは伸びましたが計算量は減ってます。減ってるんです。
説明は面倒だな本当に。正直図でもないとやってられない。なんでこんなの書いてたんだっけ?
このあとは事前計算分のかなりの量が解像度が変わらない限り固定であることを利用してグローバル領域にその数字をとって置いたり。分散処理をかましたりしました。
for(int index_x = 0; index_x < dst_w; index_x++){//ループその2
int yc_y = 0, yc_cb = 0, yc_cr = 0;//テンポラリ
for(int offset_y = 0; offset_y < lpd_h; offset_y++){//ループその3
for(int offset_x = 0; offset_x < lpd_w; offset_x++){//ループその4
//さぁここは何をやってるでしょうΛ||Λ
yc_y += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].y;
yc_cb += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].cb;
yc_cr += fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].cr;
}//ループその4終わり
}//ループその3終わり
//総和を割るとこ
fpip->ycp_temp[index_x + index_y * max_w].y = static_cast
fpip->ycp_temp[index_x + index_y * max_w].cb = static_cast
fpip->ycp_temp[index_x + index_y * max_w].cr = static_cast
}//ループその2終わり
}//ループその1終わり
ループその1と2は良いでしょう。縦と横の目的解像度分ループしますよと。
そしてそれぞれのピクセル毎の総和を一時保存する
そして問題のループその3と4。ここではlpd_w*lpd_h回のループということになります。
最内周が何回まわってくるかというとdst_w*dst_h*lpd_w*lpd_h回。並び替えるとdst_w*lpd_w*lpd_h*dst_h回。
lpdは目的解像度にかけると目的解像度と元の解像度の最大公約数になる係数なので、
縦横それぞれの最大公約数をかけた数のループ回数ということになります。
どんぐらい腐ってるかっていうとキリの悪い数でやろうものなら回数が余裕で億に届きます。
そしてループ内の問題のコードです。
fpip->ycp_edit[x + y * max_w].y
上の様に記述した場合描画領域の横x、縦yの座標の輝度が返ってくるわけです
fpip->ycp_edit[(index_x * lpd_w + offset_x) / lps_w + ((index_y * lpd_h + offset_y) / lps_h) * max_w].y;
であるのならば
横の座標:(index_x * lpd_w + offset_x) / lps_w
盾の座標:(index_y * lpd_h + offset_y) / lps_h
ということになります。これもイミフですが端折って説明すると、
「元の画像を拡大したものにおけるある座標に対応するリサイズ先の画像の座標」を示しています。
それでまぁこれに割り算が入っているのでひどいという。
ベンチマークになるよ。やったねたえちゃん!
いくらなんでもバカ正直にn回加算する演算をn回のループで表現するのはバカなので、
同じピクセルからは一度しか画素の情報をとってこないように書き換えた結果がしたです。
typedef const PIXEL_YC * const ro_YCP;
typedef PIXEL_YC * const rw_YCP;
for(int index_y = 0; index_y < dst_h; index_y++){
//可読性対策
const int index_lcm_y = index_y * lpd_h;
//上端下端
const int edge_top = (Lcm_h - index_lcm_y) % lps_h;
const int edge_bottom = (index_lcm_y + lpd_h) % lps_h;
//重複確認
const int divide_ratio_y = (edge_top + edge_bottom > lpd_h)?edge_top + edge_bottom:lpd_h;
//可読性対策
const int begin_edge_bottom = lpd_h - edge_bottom;
//開始地点終了地点
const int poz_edge_top = (index_lcm_y / lps_h) * max_w;
const int poz_edge_bottom = ((index_lcm_y + begin_edge_bottom) / lps_h) * max_w;
for(int index_x = 0; index_x < dst_w; index_x++){
//可読性対策
const int index_lcm_x = index_x * lpd_w;
//左端右端
const int edge_left = (Lcm_w - index_lcm_x) % lps_w;
const int edge_right = (index_lcm_x + lpd_w) % lps_w;
//重複確認はあとで。
//可読性対策
const int begin_edge_right = lpd_w - edge_right;
//開始地点終了地点
const int poz_edge_left = index_lcm_x / lps_w;
const int poz_edge_right = (index_lcm_x + begin_edge_right) / lps_w;
//piece * poz->?でintの範囲をオーバーしうるので
//どこかしらで__int64にしておくこと
__int64 yc64_y = 0, yc64_cb = 0, yc64_cr = 0;
//上段左
if(edge_left || edge_top){
const __int64 piece = edge_left * edge_top;
ro_YCP poz = src_ycp + poz_edge_left + poz_edge_top;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//上段中
if(edge_top){
const __int64 piece = lps_w * edge_top;
ro_YCP temp_poz = src_ycp + poz_edge_top;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//上段右
if(edge_right || edge_top){
const __int64 piece = edge_right * edge_top;
ro_YCP poz = src_ycp + poz_edge_right + poz_edge_top;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//中段左
if(edge_left){
const __int64 piece = edge_left * lps_h;
ro_YCP temp_poz = src_ycp + poz_edge_left;
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP poz = temp_poz + (index_lcm_y + offset_y) / lps_h * max_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//中段中
//pieceは必ず非ゼロ
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP temp_poz = src_ycp + (index_lcm_y + offset_y) / lps_h * max_w;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//中段右
if(edge_right){
const __int64 piece = edge_right * lps_h;
ro_YCP temp_poz = src_ycp + poz_edge_right;
for(int offset_y = edge_top; offset_y < begin_edge_bottom; offset_y += lps_h){
ro_YCP poz = temp_poz + (index_lcm_y + offset_y) / lps_h * max_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//下段左
if(edge_left || edge_bottom){
const __int64 piece = edge_left * edge_bottom;
ro_YCP poz = src_ycp + poz_edge_left + poz_edge_bottom;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
//下段中
if(edge_bottom){
const __int64 piece = lps_w * edge_bottom;
ro_YCP temp_poz = src_ycp + poz_edge_bottom;
for(int offset_x = edge_left; offset_x < begin_edge_right; offset_x += lps_w){
ro_YCP poz = temp_poz + (index_lcm_x + offset_x) / lps_w;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
}
//下段右
if(edge_right || edge_bottom){
const __int64 piece = edge_right * edge_bottom;
ro_YCP poz = src_ycp + poz_edge_right + poz_edge_bottom;
yc64_y += piece * poz->y;
yc64_cb += piece * poz->cb;
yc64_cr += piece * poz->cr;
}
rw_YCP dst = dst_ycp + index_x + index_y * max_w;
//重複確認および確定
const int divide_ratio = divide_ratio_y * ((edge_left + edge_right > lpd_w)?edge_left + edge_right : lpd_w);
//総和で割るとこ
fpip->ycp_temp[index_x + index_y * max_w].y = static_cast
fpip->ycp_temp[index_x + index_y * max_w].cb = static_cast
fpip->ycp_temp[index_x + index_y * max_w].cr = static_cast
}
}
コードは伸びましたが計算量は減ってます。減ってるんです。
説明は面倒だな本当に。正直図でもないとやってられない。なんでこんなの書いてたんだっけ?
このあとは事前計算分のかなりの量が解像度が変わらない限り固定であることを利用してグローバル領域にその数字をとって置いたり。分散処理をかましたりしました。
PR
Comment Form