📄 vframe.c
字号:
#include "vframe.h"VFrame::VFrame(int w, int h){ this->w = w; this->h = h; rows = new VPixel*[h + 1]; for(int i = 0; i < h + 1; i++) { rows[i] = new VPixel[w + 1];//printf("%x\n", rows[i]); }}VFrame::~VFrame(){//printf("VFrame::~VFrame\n"); for(int i = 0; i < h + 1; i++) {//printf("%x\n", rows[i]); delete rows[i]; } delete rows;}VFrame::transfer_from(VFrame *frame, long position, int center_x, int center_y, float zoom, float opacity, int fast){// get boundaries int in_row1 = (int)(center_y - frame->h / 2 / zoom); int in_row2 = (int)(center_y + frame->h / 2 / zoom); int in_column1 = (int)(center_x - frame->w / 2 / zoom); int in_column2 = (int)(center_x + frame->w / 2 / zoom); int out_row1 = 0; int out_row2 = 0; int out_column1 = 0; int out_column2 = 0;// correct boundaries if(in_row1 < 0) { out_row1 += -(int)(in_row1 * zoom); in_row1 = 0; } if(in_row2 > frame->h) { out_row2 -= (int)((in_row2 - frame->h) * zoom); in_row2 = frame->h; } if(in_column1 < 0) { out_column1 += -(int)(in_column1 * zoom); in_column1 = 0; } if(in_column2 > frame->w) { out_column2 -= (int)((in_column2 - frame->w) * zoom); in_column2 = frame->w; } if(out_row1 < 0) { in_row1 += -(int)(out_row1 / zoom); out_row1 = 0; } if(out_row2 > frame->h) { in_row2 -= (int)((out_row2 - frame->h) / zoom); out_row2 = frame->h; } if(out_column1 < 0) { in_column1 += -(int)(out_column1 / zoom); out_column1 = 0; } if(out_column2 > frame->w) { in_column2 -= (int)((out_column2 - frame->w) / zoom); out_column2 = frame->w; } if(zoom > 1) { transfer_enlarge(frame, in_row1, out_row1, in_row2 - in_row1, out_row2 - out_row1, in_column1, out_column1, in_column2 - in_column1, out_column2 - out_column1, opacity, fast); } else if(zoom == 1) { for(int i = out_row1, j = in_row1; i < out_row2; i++, j++) { transfer_row_direct(&rows[i][out_column1], &(frame->rows[j][in_column1]), out_column2 - out_column1, opacity); } } else { transfer_reduce(frame, in_row1, out_row1, in_row2 - in_row1, out_row2 - out_row1, in_column1, out_column1, in_column2 - in_column1, out_column2 - out_column1, opacity, fast); }}VFrame::transfer_enlarge(VFrame *input, int in_row1, int out_row1, int in_height, int out_height, int in_column1, int out_column1, int in_width, int out_width, float opacity, int fast){ int input_table_x[out_width]; int input_table_y[out_height]; float input_fraction_table_x[out_width]; float input_fraction_table_y[out_height]; get_enlarge_tables(input_table_x, input_table_y, input_fraction_table_x, input_fraction_table_y, in_width, out_width, in_height, out_height); if(fast) { VPixel new_row[out_width]; int last_input_row = input_table_y[0]; VPixel **input_rows, **output_rows; input_rows = &(input->rows[in_row1]); output_rows = &rows[out_row1]; enlarge_row_fast(new_row, &input_rows[last_input_row][in_column1], out_width, input_table_x); for(int i = 0; i < out_height; i++) { if(last_input_row != input_table_y[i]) { last_input_row = input_table_y[i]; enlarge_row_fast(new_row, &input_rows[last_input_row][in_column1], out_width, input_table_x); } transfer_row_direct(&output_rows[i][out_column1], new_row, out_width, opacity); } } else { VPixel *next_row, *previous_row; VPixel **input_rows, **output_rows; VPixel *temp; int i = 0, j = 0; int next_row_number; input_rows = &(input->rows[in_row1]); output_rows = &rows[out_row1]; next_row = new VPixel[out_width]; previous_row = new VPixel[out_width]; next_row_number = input_table_y[i]; enlarge_row(next_row, &input_rows[next_row_number][in_column1], out_width, input_table_x, input_fraction_table_x); for(i = 0; i < out_height; i++) { if(input_table_y[i] >= next_row_number) {// swap fake rows temp = previous_row; previous_row = next_row; next_row = temp;// get a new row next_row_number = input_table_y[i] + 1; enlarge_row(next_row, &input_rows[next_row_number][in_column1], out_width, input_table_x, input_fraction_table_x); } transfer_row_enlarge(&output_rows[i][out_column1], previous_row, next_row, out_width, input_fraction_table_y[i], opacity); } delete next_row; delete previous_row; }}VFrame::get_enlarge_tables(int *input_table_x, int *input_table_y, float *input_fraction_table_x, float *input_fraction_table_y, int in_width, int out_width, int in_height, int out_height){ int output_pixel; float input_pixel; float input_advance = in_width / out_width; for(output_pixel = 0, input_pixel = 0; output_pixel < out_width; input_pixel += input_advance, output_pixel++) { input_table_x[output_pixel] = (int)input_pixel; input_fraction_table_x[output_pixel] = input_pixel - (int)input_pixel; } input_advance = in_height / out_height; for(output_pixel = 0, input_pixel = 0; output_pixel < out_height; input_pixel += input_advance, output_pixel++) { input_table_y[output_pixel] = (int)input_pixel; input_fraction_table_y[output_pixel] = input_pixel - (int)input_pixel; }}VFrame::transfer_reduce(VFrame *input, int in_row1, int out_row1, int in_height, int out_height, int in_column1, int out_column1, int in_width, int out_width, float opacity, int fast){ if(fast) { int input_table_x[out_width]; int input_table_y[out_height]; get_fast_reduce_tables(input_table_x, input_table_y, in_width, out_width, in_height, out_height); VPixel **input_rows, **output_rows; input_rows = &(input->rows[in_row1]); output_rows = &rows[out_row1]; for(int i = 0; i < in_height; i++) { reduce_row_fast(&output_rows[i][out_column1], &input_rows[input_table_y[i]][in_column1], input_table_x, out_width, opacity); } } else { int output_table_x[in_width]; int output_table_y[in_height]; float output_fraction_table_x[in_width]; float output_fraction_table_y[in_height]; get_reduce_tables(output_table_x, output_table_y, output_fraction_table_x, output_fraction_table_y, in_width, out_width, in_height, out_height); int output_pixel_old; VPixel new_row[out_width]; VPixel **input_rows, **output_rows; input_rows = &(input->rows[in_row1]); output_rows = &rows[out_row1]; clear_row(new_row, out_width); for(int i = 0, output_pixel_old = output_table_y[0]; i < in_height; i++) { if(output_pixel_old != output_table_y[i]) { transfer_row_direct(&output_rows[output_pixel_old][out_column1], new_row, out_width, opacity); output_pixel_old = output_table_y[i]; clear_row(new_row, out_width); } reduce_row(new_row, &input_rows[i][in_column1], in_width, output_table_x, output_fraction_table_x, output_fraction_table_y[i]); } }}VFrame::clear_row(VPixel *row, int width){ for(int i = 0; i < width; i++) { row[i].red = row[i].green = row[i].blue = row[i].alpha = 0; }}VFrame::get_reduce_tables(int *output_table_x, int *output_table_y, float *output_fraction_table_x, float *output_fraction_table_y, int in_width, int out_width, int in_height, int out_height){ int input_pixel; int output_fraction_pixel, output_fraction_total, output_pixel_old; float output_pixel; float output_advance = out_width / in_width; int i; for(output_pixel = 0, input_pixel = 0, output_fraction_pixel = 0, output_fraction_total = 0, output_pixel_old = 0; input_pixel < in_width; input_pixel++, output_pixel += output_advance, output_fraction_total++) { if((int)output_pixel != output_pixel_old) { for( ; output_fraction_pixel < input_pixel; output_fraction_pixel++) output_fraction_table_x[output_fraction_pixel] = (float)1 / output_fraction_total; output_fraction_total = 0; output_pixel_old = (int)output_pixel; } output_table_x[input_pixel] = (int)output_pixel; } output_advance = out_height / in_height; for(output_pixel = 0, input_pixel = 0, output_fraction_pixel = 0, output_fraction_total = 0, output_pixel_old = 0; input_pixel < in_height; input_pixel++, output_pixel += output_advance, output_fraction_total++) { if((int)output_pixel != output_pixel_old) { for( ; output_fraction_pixel < input_pixel; output_fraction_pixel++) output_fraction_table_y[output_fraction_pixel] = (float)1 / output_fraction_total; output_fraction_total = 0; output_pixel_old = (int)output_pixel; } output_table_y[input_pixel] = (int)output_pixel; }} VFrame::get_fast_reduce_tables(int *output_table_x, int *output_table_y, int in_width, int out_width, int in_height, int out_height){ float input_pixel; int output_pixel; float input_advance = in_width / out_width; for(input_pixel = 0, output_pixel = 0; output_pixel < out_width; input_pixel += input_advance, output_pixel++) { output_table_x[output_pixel] = (int)input_pixel; } input_advance = in_height / out_height; for(input_pixel = 0, output_pixel = 0; output_pixel < out_height; input_pixel += input_advance, output_pixel++) { output_table_y[output_pixel] = (int)input_pixel; }}VFrame::reduce_row(VPixel *output, VPixel *input, int in_width, int *output_table_x, float *output_fraction_table_x, float y_fraction){ float fraction; int pixel; for(int i = 0; i < in_width; i++) { fraction = output_fraction_table_x[i] * y_fraction; pixel = output_table_x[i]; output[pixel].red += (int)(input[i].red * fraction); output[pixel].green += (int)(input[i].green * fraction); output[pixel].blue += (int)(input[i].blue * fraction); output[pixel].alpha += (int)(input[i].alpha * fraction); }}VFrame::reduce_row_fast(VPixel *output, VPixel *input, int *input_table_x, int out_width, float opacity){ for(int i = 0; i < out_width; i++) { overlay_pixel(&output[i], &input[input_table_x[i]], opacity); }}VFrame::enlarge_row(VPixel *output, VPixel *input, int out_columns, int *input_table_x, float *input_fraction_table_x){ VPixel *left_pixel, *right_pixel; float ratio, inv_ratio; int right_pixel_number, i = 0; right_pixel_number = input_table_x[i]; right_pixel = &input[right_pixel_number]; for(i = 0; i < out_columns; i++) { if(input_table_x[i] >= right_pixel_number) { left_pixel = right_pixel; right_pixel_number = input_table_x[i] + 1; right_pixel = &input[right_pixel_number]; } ratio = input_fraction_table_x[i]; inv_ratio = 1 - ratio; output[i].red = (int)(left_pixel->red * inv_ratio + right_pixel->red * ratio); output[i].green = (int)(left_pixel->green * inv_ratio + right_pixel->green * ratio); output[i].blue = (int)(left_pixel->blue * inv_ratio + right_pixel->blue * ratio); output[i].alpha = (int)(left_pixel->alpha * inv_ratio + right_pixel->alpha * ratio); }}VFrame::enlarge_row_fast(VPixel *output, VPixel *input, int out_columns, int *input_table_x){ int input_pixel; for(int i = 0; i < out_columns; i++) { input_pixel = input_table_x[i]; output[i].red = input[input_table_x[input_pixel]].red; output[i].green = input[input_table_x[input_pixel]].green; output[i].blue = input[input_table_x[input_pixel]].blue; output[i].alpha = input[input_table_x[input_pixel]].alpha; }}VFrame::transfer_row_enlarge(VPixel *output_row, VPixel *previous_row, VPixel *next_row, int columns, float input_ratio, float opacity){ float inv_ratio = 1 - input_ratio; int i = 0; VPixel new_pixel; for(i = 0; i < columns; i++) { new_pixel.red = (int)(previous_row[i].red * inv_ratio + next_row[i].red * input_ratio); new_pixel.green = (int)(previous_row[i].green * inv_ratio + next_row[i].green * input_ratio); new_pixel.blue = (int)(previous_row[i].blue * inv_ratio + next_row[i].blue * input_ratio); new_pixel.alpha = (int)(previous_row[i].alpha * inv_ratio + next_row[i].alpha * input_ratio); overlay_pixel(&output_row[i], &new_pixel, opacity); }}VFrame::transfer_row_direct(VPixel *output, VPixel *input, int out_columns, float opacity){ for(int i = 0; i < out_columns; i++) { overlay_pixel(&output[i], &input[i], opacity); }}VFrame::overlay_pixel(VPixel *output, VPixel *input, float opacity){ float input_opacity = (float)input->alpha / VMAX; input_opacity *= opacity; float output_opacity = (float)output->alpha / VMAX * (1 - input_opacity); output->red = (int)(output->red * output_opacity + input->red * input_opacity); output->green = (int)(output->green * output_opacity + input->green * input_opacity); output->blue = (int)(output->blue * output_opacity + input->blue * input_opacity); output->alpha = (int)(output->alpha * output_opacity + input->alpha * input_opacity);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -