CCF-画字符-详细的注释
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main3 {
static int R, G, B;
static String reset = "\\x1B\\x5B\\x30\\x6D";
public static void main(String[] args) {
//test();
run();
}
public static void test() {
//测试代码
}
public static void run() {
FastIO io = new FastIO();
io.init(System.in);
int width = io.nextInt(), height = io.nextInt();
int pw = io.nextInt(), qh = io.nextInt();
int[][][] image = new int[height][width][3];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
hexToRGB(io.next());
image[i][j][0] = R;
image[i][j][1] = G;
image[i][j][2] = B;
}
}
int count = pw * qh;//一个小块中像素点的数量
int rAvg = 0, gAvg = 0, bAvg = 0;
int preR = 0, preG = 0, preB = 0;
StringBuilder result = new StringBuilder();
boolean first = true;
for (int i = 0; i < height; i += qh) {
for (int j = 0; j < width; j += pw) {
int rSum = 0, gSum = 0, bSum = 0;
for (int y = i; y < i + qh; y++) {
for (int x = j; x < j + pw; x++) {
rSum += image[y][x][0];
gSum += image[y][x][1];
bSum += image[y][x][2];
}
}
rAvg = rSum / count;
gAvg = gSum / count;
bAvg = bSum / count;
if (first) {
//一行的开始,此时背景色已经是默认色,所以如果该块等于默认色,则什么都不做。
// 只有该块的颜色不等于默认色的时候才输出默认色
if (!(rAvg == 0 && gAvg == 0 && bAvg == 0)) {
changeBackground(rAvg, gAvg, bAvg, result);
}
first = false;
} else if (!(rAvg == preR && gAvg == preG && bAvg == preB)) {
//如果该块的颜色不等于上一块的颜色,且等于默认色输出重置序列
if (rAvg == 0 && gAvg == 0 && bAvg == 0) {
result.append(reset);
} else {
//如果该块的颜色不等于上一块的颜色,且不等于默认色,那么改变输出背景色序列
changeBackground(rAvg, gAvg, bAvg, result);
}
}
result.append("\\x20");
preR = rAvg;
preG = gAvg;
preB = bAvg;
}
//如果该行结束后时的背景色不等于默认色,则输出重置序列
if (!(rAvg == 0 && gAvg == 0 && bAvg == 0)) {
result.append(reset);
}
first = true;
//添加一个换行符
result.append("\\x0A");
}
//只在最后输出结果,而不是每一行就输出一次,这样可以减少IO次数,节约用时
System.out.print(result.toString());
}
/**
* 将颜色的16进制转换成(R,G,B)的形式
* @param hex 颜色的16进制值
*/
public static void hexToRGB(String hex) {
if (hex.length() == 4) {
//#abc->#aabbcc的情况
R = Integer.parseInt(hex.substring(1, 2) + hex.substring(1, 2), 16);
G = Integer.parseInt(hex.substring(2, 3) + hex.substring(2, 3), 16);
B = Integer.parseInt(hex.substring(3, 4) + hex.substring(3, 4), 16);
} else if (hex.length() == 2) {
//#a->#aaaaaa的情况
R = Integer.parseInt(hex.substring(1,2)+hex.substring(1,2), 16);
G = R;
B = R;
} else {
//#aabbcc的情况
R = Integer.parseInt(hex.substring(1, 3), 16);
G = Integer.parseInt(hex.substring(3, 5), 16);
B = Integer.parseInt(hex.substring(5, 7), 16);
}
}
/**
* 改变背景色
*/
public static void changeBackground(int R, int G, int B, StringBuilder hexOut) {
// ESC[48;2
hexOut.append("\\x1B\\x5B\\x34\\x38\\x3B\\x32\\x3B");
getHexOrder(R,hexOut);
// 3B对应字符 ;
hexOut.append("\\x3B");
getHexOrder(G, hexOut);
hexOut.append("\\x3B");
getHexOrder(B, hexOut);
// 6D 对应字符m
hexOut.append("\\x6D");
}
/**
* 获取一个分量每位对应的16进制,并且按照输出的顺序进行拼接
* @param a 颜色int值
*/
public static void getHexOrder(int a, StringBuilder hexOut) {
if (a >= 100) {
//该颜色分量有3位
hexOut.append("\\x");
// 48对应ACSII字符表中的'0' 字符,因为我们最终的输出时一个字符对应的转义序列,而不是10进制的int值的16进制,所以需要加上48
hexOut.append(Integer.toHexString(a / 100+48));
hexOut.append("\\x");
hexOut.append(Integer.toHexString(a / 10 % 10+48));
hexOut.append("\\x");
hexOut.append(Integer.toHexString(a % 10+48));
} else if (a >= 10) {
//颜色分量有2位
hexOut.append("\\x");
hexOut.append(Integer.toHexString(a / 10+48));
hexOut.append("\\x");
hexOut.append(Integer.toHexString(a % 10+48));
}else {
//颜色分量只有一位
hexOut.append("\\x");
hexOut.append(Integer.toHexString(48 + a));
}
}
static class FastIO {
BufferedReader reader;
StringTokenizer tokenizer;
void init(InputStream inputStream) {
reader = new BufferedReader(new InputStreamReader(inputStream));
tokenizer = new StringTokenizer("");
}
//读入一个字符串
String next() {
while (!tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return tokenizer.nextToken();
}
//读入一整行
String nextLine() {
while (!tokenizer.hasMoreElements()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return tokenizer.nextToken("\n");
}
//读入int类型数据
int nextInt() {
return Integer.parseInt(next());
}
//读入double类型数据
double nextDouble() {
return Double.parseDouble(next());
}
}
}
CCF-画字符-详细的注释的更多相关文章
- CCF 201909-3 字符画
CCF 201909-3 字符画 题意: 将n * m的RGB图片压缩成q * p的块,每块为该原像素的平均值,我们暂且称之为像素块(代码注释为字符块) . 输入n行m列的RGB图片: 第一行:图片的 ...
- Qt简单项目--加法计算器(详细代码注释)
Qt的简单案例--加法计算器(详细代码注释) 一.项目结构 二.项目代码 widget.h #ifndef WIDGET_H #define WIDGET_H //预编译指令, 为了避免头文件被重复包 ...
- ccf 201409-3 字符串匹配(toupper,tolower)
ccf 201409-3 字符串匹配(toupper,tolower) 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一 ...
- QT学习 之 对话框 (四) 字体对话框、消息对话框、文件对话框、进程对话框(超详细中文注释)
QMessageBox类: 含有Question消息框.Information消息框.Warning消息框和Critical消息框等 通常有两种方式可以来创建标准消息对话框: 一种是采用“基于属性”的 ...
- qt下的时钟程序(简单美丽,继承自QWidget的Clock,用timer调用update刷新,然后使用paintEvent作画就行了,超详细中文注释)good
最近抽空又看了下qt,发现用它来实现一些东西真的很容易比如下面这个例子,绘制了个圆形的时钟,但代码却清晰易懂[例子源自奇趣科技提供的例子]因为清晰,所以就只写注释了,吼吼其实也就这么几行代码头文件 / ...
- opencv 之 icvCreateHidHaarClassifierCascade 分类器信息初始化函数部分详细代码注释。
请看注释.这个函数,是人脸识别主函数,里面出现过的函数之一,作用是初始化分类器的数据,就是一个xml文件的数据初始化. static CvHidHaarClassifierCascade* icvCr ...
- 使用graphics2D给图片上画字符
//读取图片BufferedImage frontImage = ImageIO.read(new File(eCardXMLConfigManager.geteCardXMLConfigManage ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 微信支付接口--超详细带注释代码--Demo
如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 微 ...
随机推荐
- Jackson替换fastjson
为什么要替换fastjson 工程里大量使用了fastjson作为序列化和反序列化框架,甚至ORM在处理部分字段也依赖fastjson进行序列化和反序列化.那么作为大量使用的基础框架,为什么还要进行替 ...
- C#详解类型,变量与对象
本节内容: 1.什么是类型(Type) 2.类型在C#语言中的作用 3.C#语言的类型系统 4.变量.对象与内存 1.什么是类型(type) 类型又名数据类型(Date Type),是数据在内存中存储 ...
- php下载文件,线上文件下载
1.多个文件下载 <?php /* 把知道的图片问题名字做成一个数组 */ $mp4 = ['123','456']; /* count($mp4) 类似于 js 的 $mp4.length * ...
- 解决js计算0.1+0.2 !==0.3
经常做用js数据运算的同学应该了解,在js中,0.1+0.2不会等于0.3,而是等于: 我一开始发现这个bug的时候也觉得很奇怪,那怎么去解决这个bug,让0.1+0.2 最后能得到0.3呢? 方法一 ...
- 两种unity双击事件
有时候需要用到双击事件,而unity未提供双击控件,在此提供两种双击事件方法,进攻参考: 1)此方法为通过unityevent来实现 首先新建image(或其他不带点击事件的控件),添加如下脚本,然后 ...
- 第一篇 Flask初识
一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不 ...
- 2018.8.10 python中的迭代器
主要内容: 1.函数名的使用 2.闭包 3.迭代器 一.函数名的运用 函数名是一个变量,但他是一个特殊的变量,与括号配合可执行函数的变量. 1.函数名的内存地址 def func(): print(' ...
- python dict(字典)
补充知识点1: 数据类型的划分:可变数据类型.不可变数据类型 可变数据类型: 元组,bool,int,str --可哈希 不可变数据类型: list,dict,set ...
- 【MySQL】MySQL 8.0.X的安装与卸载命令
1.请读者自行下载MySQL Server https://dev.mysql.com/downloads/mysql/ 2.解压.zip文件 将mysql-8.0.12-winx64.zip解压到 ...
- API 网关知识看这篇就足够了!
本文已经收录自 JavaGuide (60k+ Star[Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.) 本文授权转载自:https://github.com/java ...