LCUI_API int LCUIScreen_PutGraph (LCUI_Graph *graph, LCUI_Pos des_pos ) { int total, y, n, des_row_x, src_row_x, des_x, src_x; LCUI_Graph *src; LCUI_Rect cut, src_rect; LCUI_Size screen_size; uchar_t *des_ptr; src = Graph_GetQuote( graph ); src_rect = Graph_GetValidRect( graph ); screen_size = LCUIScreen_GetSize(); if(!Graph_IsValid(src)) { return -1; } if(des_pos.x >= screen_size.w || des_pos.y >= screen_size.h) { return -1; } des_ptr = pixel_mem; Graph_Lock( src ); /* 获取图像的截取区域 */ if( LCUIRect_GetCutArea( screen_size, Rect( des_pos.x, des_pos.y, src_rect.width, src_rect.height ), &cut )) { des_pos.x += cut.x; des_pos.y += cut.y; } /* 根据二维坐标和图像尺寸,计算源图像的起始读取点的一维坐标 */ src_row_x = (cut.y + src_rect.y) * src->width + cut.x + src_rect.x; /* 根据二维坐标和屏幕尺寸,计算帧缓冲的起始写入点的一维坐标 */ des_row_x = des_pos.y * screen_size.w + des_pos.x; for(y=0; y<cut.height; ++y) { src_x = src_row_x; des_x = des_row_x; total = src_x + cut.width; for (; src_x < total; ++des_x,++src_x) { n = des_x << 2; des_ptr[n++] = src->rgba[2][src_x]; des_ptr[n++] = src->rgba[1][src_x]; des_ptr[n++] = src->rgba[0][src_x]; } src_row_x += src->width; /* DIB扫描行是上下颠倒的,因此是从行尾到行首递减 */ des_row_x += screen_size.w; } Graph_Unlock( src ); return 0; }
int load_jpeg(const char *filepath, LCUI_Graph *out) /* 功能:载入并解码jpg图片 */ { #ifdef USE_LIBJPEG FILE *fp; fp = fopen(filepath,"r"); if(fp == NULL) { return -1; } int row_stride,jaka; int x,y, m, n, k; short int JPsyg; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; JSAMPARRAY buffer; if( fread( &JPsyg, sizeof(short int), 1, fp ) ) { if ( JPsyg != -9985 ) { /* 如果不是jpg图片 */ return 1; } } rewind(fp); cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return 2; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo,fp); (void) jpeg_read_header(&cinfo,IS_TRUE); (void) jpeg_start_decompress(&cinfo); jaka = cinfo.num_components; //if (jaka==3) printf("color\n"); else printf("grayscale\n"); out->have_alpha = IS_FALSE; /* 设置为无透明度 */ n = Graph_Create(out, cinfo.output_width, cinfo.output_height); if( n != 0 ){ printf("load_jpeg(): error: "MALLOC_ERROR); return 1; } row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray)( (j_common_ptr) &cinfo,JPOOL_IMAGE,row_stride,1); Graph_Lock( out, 1 ); for(y=0; cinfo.output_scanline <cinfo.output_height; ++y) { (void) jpeg_read_scanlines(&cinfo, buffer, 1); m = y*out->width; if ( jaka == 3 ) { for (x=0;x<out->width;x++) { n = x+m; k=x*3; out->rgba[0][n]=buffer[0][k++]; out->rgba[1][n]=buffer[0][k++]; out->rgba[2][n]=buffer[0][k++]; } } else { for (x=0;x<out->width;x++) { n = x+m; out->rgba[0][n]=buffer[0][x]; out->rgba[1][n]=buffer[0][x]; out->rgba[2][n]=buffer[0][x]; } } } out->type = TYPE_JPG;//图片类型为jpg Graph_Unlock( out ); (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); #else printf("warning: not JPEG support!"); #endif return 0; }
int Graph_Draw_Border(LCUI_Graph *src,LCUI_RGB color, LCUI_Border border) /* 功能:为图形边缘绘制矩形边框 */ { int x,y,count, k, start_x,start_y; if(Graph_Valid(src)) { /* 绘制上边的线 */ Graph_Lock(src, 1); for(y=0;y<border.top;++y) { k = y * src->width; for(x = 0; x < src->width; ++x) { count = k + x; src->rgba[0][count] = color.red; src->rgba[1][count] = color.green; src->rgba[2][count] = color.blue; if(Graph_Have_Alpha(src)) src->rgba[3][count] = 255; } } start_y = src->height - border.bottom; /* 绘制下边的线 */ for(y=0;y<border.bottom;++y) { k = (start_y+y) * src->width; for(x=0;x<src->width;++x) { count = k + x; src->rgba[0][count] = color.red; src->rgba[1][count] = color.green; src->rgba[2][count] = color.blue; if(Graph_Have_Alpha(src)) src->rgba[3][count] = 255; } } /* 绘制左边的线 */ for(y=0;y<src->height;++y) { k = y * src->width; for(x=0;x<border.left;++x) { count = k + x; src->rgba[0][count] = color.red; src->rgba[1][count] = color.green; src->rgba[2][count] = color.blue; if(Graph_Have_Alpha(src)) src->rgba[3][count] = 255; } } /* 绘制右边的线 */ start_x = src->width - border.right; for(y=0;y<src->height;++y) { k = y * src->width + start_x; for(x=0;x<border.right;++x) { count = k + x; src->rgba[0][count] = color.red; src->rgba[1][count] = color.green; src->rgba[2][count] = color.blue; if(Graph_Have_Alpha(src)) src->rgba[3][count] = 255; } } /* 边框线绘制完成 */ Graph_Unlock(src); } else return -1; return 0; }
LCUI_EXPORT(int) write_png(const char *file_name, LCUI_Graph *graph) /* 将图像数据写入至png文件 */ { #ifdef USE_LIBPNG FILE *fp; int j, i, temp, pos; png_byte color_type; png_structp png_ptr; png_infop info_ptr; png_bytep * row_pointers; if(!Graph_IsValid(graph)) { printf("write_png(): graph is not valid\n"); return -1; } /* create file */ fp = fopen(file_name, "wb"); if (!fp) { printf("write_png(): File %s could not be opened for writing\n", file_name); return -1; } /* initialize stuff */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { printf("write_png(): png_create_write_struct failed\n"); return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { printf("write_png(): png_create_info_struct failed\n"); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { printf("write_png(): Error during init_io\n"); return -1; } png_init_io(png_ptr, fp); /* write header */ if (setjmp(png_jmpbuf(png_ptr))) { printf("write_png(): Error during writing header\n"); return -1; } Graph_Lock(graph); if(Graph_HaveAlpha(graph)) { color_type = PNG_COLOR_TYPE_RGB_ALPHA; } else { color_type = PNG_COLOR_TYPE_RGB; } png_set_IHDR(png_ptr, info_ptr, graph->width, graph->height, graph->bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); /* write bytes */ if (setjmp(png_jmpbuf(png_ptr))) { printf("write_png(): Error during writing bytes\n"); Graph_Unlock(graph); return -1; } if(Graph_HaveAlpha(graph)) { temp = (4 * graph->width); } else { temp = (3 * graph->width); } row_pointers = (png_bytep*)malloc(graph->height*sizeof(png_bytep)); for(i=0,pos=0; i < graph->height; i++) { row_pointers[i] = (png_bytep)malloc(sizeof(unsigned char)*temp); for(j=0; j < temp; ++pos) { row_pointers[i][j++] = graph->rgba[0][pos]; // red row_pointers[i][j++] = graph->rgba[1][pos]; // green row_pointers[i][j++] = graph->rgba[2][pos]; // blue if(Graph_HaveAlpha(graph)) { row_pointers[i][j++] = graph->rgba[3][pos]; // alpha } } } png_write_image(png_ptr, row_pointers); /* end write */ if (setjmp(png_jmpbuf(png_ptr))) { printf("write_png(): Error during end of write\n"); Graph_Unlock(graph); return -1; } png_write_end(png_ptr, NULL); /* cleanup heap allocation */ for (j=0; j<graph->height; j++) { free(row_pointers[j]); } free(row_pointers); fclose(fp); Graph_Unlock(graph); #else printf("warning: not PNG support!"); #endif return 0; }
int GaussianSmooth( LCUI_Graph *src, LCUI_Graph *des, double sigma ) /* 对图像进行高斯模糊处理 */ { LCUI_Graph temp; int32_t kcenter, i; uint_t x, y, ksize; uint_t temp_pos, temp_start_pos; uint_t a_src_pos, b_src_pos, src_start_pos; double amul, bmul, gmul, rmul, *kvalue_ptr; double *kernel, scale, cons, sum = 0; const double PI = 3.141592653; sigma = sigma > 0 ? sigma : -sigma; //ksize为奇数 ksize = ceil(sigma * 3) * 2 + 1; if(ksize == 1) { Graph_Copy( des, src ); return 0; } //计算一维高斯核 scale = -0.5/(sigma*sigma); cons = 1/sqrt(-scale / PI); kcenter = ksize/2; kernel = (double*) malloc( ksize*sizeof(double) ); for(i = 0; i < ksize; ++i) { int x = i - kcenter; *(kernel+i) = cons * exp(x * x * scale);//一维高斯函数 sum += *(kernel+i); } //归一化,确保高斯权值在[0,1]之间 for(i = 0; i < ksize; i++) { *(kernel+i) /= sum; } des->have_alpha = src->have_alpha; if( Graph_Create( des, src->width, src->height ) != 0 ) { return -1; } Graph_Init( &temp ); temp.have_alpha = src->have_alpha; if( Graph_Create( &temp, src->width, src->height ) != 0 ) { return -2; } Graph_Lock( src, RWLOCK_READ ); Graph_Lock( &temp, RWLOCK_WRITE ); //x方向一维高斯模糊 temp_start_pos = 0; src_start_pos = 0 - kcenter; for(y = 0; y < src->height; y++) { temp_pos = temp_start_pos; b_src_pos = src_start_pos; for(x = 0; x < src->width; x++) { sum = amul = bmul = gmul = rmul = 0; a_src_pos = b_src_pos; kvalue_ptr = kernel; for(i = -kcenter; i <= kcenter; i++) { if((x+i) >= 0 && (x+i) < src->width) { rmul += src->rgba[0][a_src_pos]*(*kvalue_ptr); gmul += src->rgba[1][a_src_pos]*(*kvalue_ptr); bmul += src->rgba[2][a_src_pos]*(*kvalue_ptr); if(src->have_alpha) { amul += src->rgba[3][a_src_pos]*(*kvalue_ptr); } sum += (*kvalue_ptr); } ++a_src_pos; ++kvalue_ptr; } temp.rgba[0][temp_pos] = rmul/sum; temp.rgba[1][temp_pos] = gmul/sum; temp.rgba[2][temp_pos] = bmul/sum; if(temp.have_alpha) { temp.rgba[3][temp_pos] = amul/sum; } ++temp_pos; ++b_src_pos; } temp_start_pos += temp.width; src_start_pos += src->width; } Graph_Unlock( &temp ); Graph_Lock( des, RWLOCK_WRITE ); Graph_Lock( &temp, RWLOCK_READ ); //y方向一维高斯模糊 src_start_pos = 0 - kcenter*temp.width; src_start_pos = 0 - kcenter*temp.width; for(x = 0; x < temp.width; x++) { temp_start_pos = x; b_src_pos = src_start_pos; for(y = 0; y < temp.height; y++) { sum = amul = bmul = gmul = rmul = 0; a_src_pos = b_src_pos; kvalue_ptr = kernel; for(i = -kcenter; i <= kcenter; i++) { if((y+i) >= 0 && (y+i) < temp.height) { rmul += temp.rgba[0][a_src_pos]*(*kvalue_ptr); gmul += temp.rgba[1][a_src_pos]*(*kvalue_ptr); bmul += temp.rgba[2][a_src_pos]*(*kvalue_ptr); if(temp.have_alpha) { amul += temp.rgba[3][a_src_pos]*(*kvalue_ptr); } sum += (*kvalue_ptr); } a_src_pos += temp.width; ++kvalue_ptr; } des->rgba[0][temp_start_pos] = rmul/sum; des->rgba[1][temp_start_pos] = gmul/sum; des->rgba[2][temp_start_pos] = bmul/sum; if(des->have_alpha) { des->rgba[3][temp_start_pos] = amul/sum; } temp_start_pos += des->width; b_src_pos += temp.width; } ++src_start_pos; } Graph_Unlock( &temp ); Graph_Unlock( des ); Graph_Unlock( src ); Graph_Free( &temp ); free(kernel); return 0; }
LCUI_API int GraphLayer_GetGraph( LCUI_GraphLayer *ctnr, LCUI_Graph *graph_buff, LCUI_Rect rect ) { int i, total; uchar_t tmp_alpha, alpha; LCUI_Pos pos, glayer_pos; LCUI_GraphLayer *glayer; LCUI_Queue glayerQ; LCUI_Rect valid_area; LCUI_Graph tmp_graph; /* 检测这个区域是否有效 */ if (rect.x < 0 || rect.y < 0) { return -1; } if (rect.x + rect.width > ctnr->graph.w || rect.y + rect.height > ctnr->graph.h ) { return -1; } if (rect.width <= 0 || rect.height <= 0) { return -2; } Graph_Init( &tmp_graph ); Queue_Init( &glayerQ, 0, NULL); Queue_UsingPointer( &glayerQ ); graph_buff->color_type = COLOR_TYPE_RGB; /* 为graph_buff分配合适尺寸的内存空间 */ Graph_Create( graph_buff, rect.width, rect.height ); /* 获取rect区域内的图层列表 */ GraphLayer_GetLayers( ctnr, rect, &glayerQ ); total = Queue_GetTotal( &glayerQ ); //_DEBUG_MSG( "total: %d\n", total ); /* 若记录数为零,则表明该区域没有图层 */ if( total <= 0 ) { /* 若没有父图层,则填充白色 */ if( ctnr == NULL ) { Graph_FillColor( graph_buff, RGB(255,255,255) ); } else { /* 否则使用父图层的图形 */ Graph_Cut( &ctnr->graph, rect, graph_buff ); } /* 销毁记录 */ Queue_Destroy( &glayerQ ); return 0; } /* 从顶层到底层遍历图层,排除被其它图层完全遮挡或者自身完全透明的图层 */ for(i=total-1; i>=0; --i) { glayer = (LCUI_GraphLayer*)Queue_Get( &glayerQ, i ); valid_area = GraphLayer_GetValidRect( ctnr, glayer ); glayer_pos = GraphLayer_GetGlobalPos( ctnr, glayer ); valid_area.x += glayer_pos.x; valid_area.y += glayer_pos.y; alpha = GraphLayer_GetRealAlpha( glayer ); /* 当前图层的透明度小于255的话,就跳过 */ if( alpha < 255 ) { continue; } /* 如果色彩类型为RGB,没有alpha通道 */ if( glayer->graph.color_type == COLOR_TYPE_RGB ) { /* 如果该图层的有效区域包含目标区域 */ if( LCUIRect_IncludeRect(valid_area, rect) ) { /* 移除底层的图层,因为已经被完全遮挡 */ for(total=i-1;total>=0; --total) { Queue_DeletePointer( &glayerQ, 0 ); } goto skip_loop; } } } skip_loop: total = Queue_GetTotal( &glayerQ ); //_DEBUG_MSG( "total: %d\n", total ); if(i <= 0) { if( ctnr == NULL ) { Graph_FillColor( graph_buff, RGB(255,255,255) ); } else { Graph_Cut ( &ctnr->graph, rect, graph_buff ); } } /* 获取图层列表中的图层 */ for(i=0; i<total; ++i) { glayer = (LCUI_GraphLayer*)Queue_Get( &glayerQ, i ); //_DEBUG_MSG("%p = Queue_Get( %p, %d )\n", glayer, &glayerQ, i); if( !glayer ) { continue; } /* 锁上该图层的互斥锁 */ Graph_Lock( &glayer->graph ); /* 获取该图层的有效区域及全局坐标 */ pos = GraphLayer_GetGlobalPos( ctnr, glayer ); valid_area = GraphLayer_GetValidRect( ctnr, glayer ); /* 引用该图层的有效区域内的图像 */ Graph_Quote( &tmp_graph, &glayer->graph, valid_area ); //_DEBUG_MSG("valid area: %d,%d,%d,%d, pos: %d,%d, size: %d,%d\n", // valid_area.x, valid_area.y, valid_area.width, valid_area.height, // pos.x, pos.y, glayer->graph.w, glayer->graph.h // ); /* 获取相对坐标 */ pos.x = pos.x - rect.x + valid_area.x; pos.y = pos.y - rect.y + valid_area.y; //_DEBUG_MSG("mix pos: %d,%d\n", pos.x, pos.y); /* 如果该图层没有继承父图层的透明度 */ if( !glayer->inherit_alpha ) { /* 直接叠加至graph_buff */ Graph_Mix( graph_buff, &tmp_graph, pos ); } else { /* 否则,计算该图层应有的透明度 */ alpha = GraphLayer_GetRealAlpha( glayer ); /* 备份该图层的全局透明度 */ tmp_alpha = glayer->graph.alpha; /* 将实际透明度作为全局透明度,参与图像叠加 */ glayer->graph.alpha = alpha; Graph_Mix( graph_buff, &tmp_graph, pos ); /* 还原全局透明度 */ glayer->graph.alpha = tmp_alpha; } /* 解锁图层 */ Graph_Unlock( &glayer->graph ); } Queue_Destroy( &glayerQ ); return 0; }