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~感谢观看! 微 ...
随机推荐
- opencv实践::对象的提取
问题描述 真实案例,对图像中对象进行提取,获取这样对象,去掉其它干扰和非目标对象. 解决思路 二值分割 + 形态学处理 +横纵比计算 #include <opencv2/opencv.hpp&g ...
- HDU 1532 Drainage Ditches(最大流 EK算法)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1532 思路: 网络流最大流的入门题,直接套模板即可~ 注意坑点是:有重边!!读数据的时候要用“+=”替 ...
- 概率图模型(PGM):贝叶斯网(Bayesian network)初探
1. 从贝叶斯方法(思想)说起 - 我对世界的看法随世界变化而随时变化 用一句话概括贝叶斯方法创始人Thomas Bayes的观点就是:任何时候,我对世界总有一个主观的先验判断,但是这个判断会随着世界 ...
- java23种设计模式(三)单例模式
原文地址:https://zhuanlan.zhihu.com/p/23713957 一.概述 1.什么是单例模式? 百度百科是这样定义的:单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个 ...
- 钢铁B2B电商案例:供应链金融如何解决供应链金融痛点
一.区块链是什么 区块链是一种按照时间顺序将数据块以特定的顺序相连的方式组合成的链式数据结构,其上存储了系统诞生以来所有交易的记录.区块链上的数据由全网节点共同维护并共同存储,同时以密码学方式保证区块 ...
- PSTAT 115 Homework4 课业解析
PSTAT 115 Homework4 课业解析 题意: 蒙特卡洛采样之拒绝采样 解析: 给定一个概率分布p(z)=p~(z)/Zp,p~(z)已知,Zp为归一化常数,为未知数.对该分布进行拒绝采样, ...
- 整理了适合新手的20个Python练手小程序
100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python. 本文附带基础视频教程:私信回复[基础]就可以获取的 [程序1] ...
- Leetcode Tags(8)Binary Search
一.475. Heaters 输入: [1,2,3],[2] 输出: 1 解释: 仅在位置2上有一个供暖器.如果我们将加热半径设为1,那么所有房屋就都能得到供暖. 输入: [1,2,3,4],[1,4 ...
- django-HttpResponse,render,redirect
1.导入相应的包 from django.shortcuts import HttpResponse, render, redirect 2.HttpResponse(返回字符串给浏览器) def i ...
- Python+Keras+TensorFlow车牌识别
这个是我使用的车牌识别开源项目的地址:https://github.com/zeusees/HyperLPR Python 依赖 Anaconda for Python 3.x on Win64 Ke ...