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-画字符-详细的注释的更多相关文章

  1. CCF 201909-3 字符画

    CCF 201909-3 字符画 题意: 将n * m的RGB图片压缩成q * p的块,每块为该原像素的平均值,我们暂且称之为像素块(代码注释为字符块) . 输入n行m列的RGB图片: 第一行:图片的 ...

  2. Qt简单项目--加法计算器(详细代码注释)

    Qt的简单案例--加法计算器(详细代码注释) 一.项目结构 二.项目代码 widget.h #ifndef WIDGET_H #define WIDGET_H //预编译指令, 为了避免头文件被重复包 ...

  3. ccf 201409-3 字符串匹配(toupper,tolower)

     ccf 201409-3 字符串匹配(toupper,tolower) 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一 ...

  4. QT学习 之 对话框 (四) 字体对话框、消息对话框、文件对话框、进程对话框(超详细中文注释)

    QMessageBox类: 含有Question消息框.Information消息框.Warning消息框和Critical消息框等 通常有两种方式可以来创建标准消息对话框: 一种是采用“基于属性”的 ...

  5. qt下的时钟程序(简单美丽,继承自QWidget的Clock,用timer调用update刷新,然后使用paintEvent作画就行了,超详细中文注释)good

    最近抽空又看了下qt,发现用它来实现一些东西真的很容易比如下面这个例子,绘制了个圆形的时钟,但代码却清晰易懂[例子源自奇趣科技提供的例子]因为清晰,所以就只写注释了,吼吼其实也就这么几行代码头文件 / ...

  6. opencv 之 icvCreateHidHaarClassifierCascade 分类器信息初始化函数部分详细代码注释。

    请看注释.这个函数,是人脸识别主函数,里面出现过的函数之一,作用是初始化分类器的数据,就是一个xml文件的数据初始化. static CvHidHaarClassifierCascade* icvCr ...

  7. 使用graphics2D给图片上画字符

    //读取图片BufferedImage frontImage = ImageIO.read(new File(eCardXMLConfigManager.geteCardXMLConfigManage ...

  8. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  9. 微信支付接口--超详细带注释代码--Demo

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 微 ...

随机推荐

  1. google::Glog

    windows下使用google的Glog库 下载glog-.tar.gz,解压. vs2013打开工程, 有四个项目 libglog libglog_static logging_unittest ...

  2. Go中http超时问题的排查

    背景 排查 推测 连接超时 疑问 http2 解决超时 并发连接数 服务端限制 真相 重试 解决办法 问题1 背景 最新有同事反馈,服务间有调用超时的现象,在业务高峰期发生的概率和次数比较高.从日志中 ...

  3. 基准测试了 ArrayList 和 LinkedList ,发现我们一直用 ArrayList 也是没什么问题的

    ArrayList 应该是 Java 中最常用的集合类型了,以至于我们说到集合就会自然而然的想到 ArrayList.很多同学都没有用过除了 ArrayList 之外的其他集合,甚至于都已经忘了除了 ...

  4. 处理 Could not find a 'KafkaClient' entry in the JAAS configuration. System property 'java.security.auth.login.config' is

    场景 某监控进程需要访问多个集群的Kafka INFO - org.apache.kafka.common.KafkaException: Failed to construct kafka cons ...

  5. OptimalSolution(4)--字符串问题(1)简单

    一.判断两个字符串是否互为变形词 问题:给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样,那么str1与str2互为变形词. 举例:str1=“1 ...

  6. mysql实现海量数据的存储、访问的解决方案

    mysql实现海量数据的存储.访问的解决方案: mysql数据库水平切分的实现原理可分为以下几个:分库,分表,主从,集群,负载均衡器等 第1章 引言 随着互联网应用的广泛普及,海量数据的存储和访问成为 ...

  7. ios发送短信验证码计时器的swift实现

    转载自:http://www.jianshu.com/p/024dd2d6e6e6# Update: Xcode 8.2.1 Swift 3 先介绍一下 属性观测器(Property Observer ...

  8. leetcode算法小题(3)

    问题描述: 判断一个数是否为回文数 class Solution {      public boolean isPalindrome(int x) {           if(x<0)    ...

  9. markdown 入门教程(完整版)

    Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 1. 标题 Markdown支持6种级别的标题,对应html标签 h1 ~ h6 ...

  10. ubuntu 制作本地yum仓库

    ubuntu 制作本地yum仓库 笔者: 张首富 W X: y18163201(请备注) qq群:895291458 时间:2019-01-31晚 今天到某银行进行软件部署的时候,碰到所有电脑都不允许 ...