Некоторое время назад появился на хабе статья о художнике , который рисует картинки в MS Excel, используя свои векторные возможности.
Но задолго до этого я наткнулся на истории о феноменальных растровых рисунках в Excel, идея которых основана на пиксель-арте.
Те.
некоторые просто уменьшают размер ячеек и используют цветовую заливку, чтобы создать своеобразную мозаику.
Выглядит довольно эффектно, хотя до качества векторных рисунков, конечно, не дотягивает. Увидев такие картинки, я, конечно, засомневался, что кому-то хватит упорства создавать их вручную, и решил поискать способ автоматизации «офисного творчества».
Задачу оказалось легко реализовать на Java при условии, что Библиотеки POI Apache , предназначенный для работы с собственными форматами Microsoft Office. Подробности под катом.
Итак, что мы имеем? Я поставил перед собой задачу создать приложение для конвертации самого обычного изображения JPG (или в принципе любого другого распространенного формата) в документ Excel. Стоит сразу упомянуть о существующих ограничениях: Ширина «картинки» не должна превышать 255 пикселей (максимальное количество столбцов на листе) максимальное количество стилей оформления (в нашем случае это количество цветов) — 4000 Таким образом, вам придется либо сначала найти и подготовить изображение (уменьшить размер и глубину цвета), либо сделать это программно.
Мы пойдём вторым путём :)
Сначала давайте набросаем класс Main нашей программы, содержащий единственный метод:
Хардкод, конечно, убогий, но для демонстрации вполне подойдет. Рассмотрим класс для чтения картинки из файла.public class Main { public static void main(String[] args) { IMGRead ir = new IMGRead(); Map<String, Object[]> data = ir.read("C:\\picture.jpg"); POIWrite pw = new POIWrite(); pw.write(data); } }
Он содержит метод собственно чтения картинки и возвращает результат в виде карты, содержащей объекты типа RGBColor, хранящие информацию о трёх компонентах цвета точки: public Map<String, Object[]> read(String fileName) {
File file = new File(fileName);
BufferedImage source, image;//source and resized images
Map<String, Object[]> data = new TreeMap<String, Object[]>();
try {
source = ImageIO.read(file);//read picture from file
int type = source.getType() == 0? BufferedImage.TYPE_INT_ARGB : source.getType();//get type
image = resizeImage(source, type);//resize
source = convert8(image);
image = source; // :)
// Getting pixel color for every pixel
for (Integer y = 0; y < image.getHeight(); y++) {
Object[] line = new Object[image.getWidth()];
for (int x = 0; x < image.getWidth(); x++) {
int clr = image.getRGB(x, y);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
line[x] = new RGBColor(red, green, blue);
}
data.put(String.format("d", y), line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return data;
}
У нас также есть метод изменения размера изображения: private static BufferedImage resizeImage(BufferedImage originalImage, int type) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
И метод уменьшения цвета (я использую восьмибитный цвет, для других вариантов см.
источник ): public static BufferedImage convert8(BufferedImage src) {
BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED);
ColorConvertOp cco = new ColorConvertOp(src.getColorModel()
.
getColorSpace(), dest.getColorModel().
getColorSpace(), null);
cco.filter(src, dest);
return dest;
}
Перейдем к классу, реализующему запись «картинки» в документ Excel. Здесь у нас есть 2 метода, первый из которых записывает в файл: public void write(Map<String, Object[]> data) {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Picture");
Map<String, HSSFCellStyle> colorToStyle = new HashMap<String, HSSFCellStyle>();
HSSFCellStyle style;
Set<String> keyset = data.keySet();
int rownum = 0;
for (String key : keyset) {
Row row = sheet.createRow(rownum++);
row.setHeight((short) 50);
Object[] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr) {
sheet.setColumnWidth(cellnum, 100);
Cell cell = row.createCell(cellnum++);
RGBColor rgb = (RGBColor) obj;
try {
style = colorToStyle.get(rgb.toString());
cell.setCellStyle(style);
} catch (Exception e) {
style = workbook.createCellStyle();
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setFillForegroundColor(setColor(workbook, rgb.getR(), rgb.getG(), rgb.getB()).
getIndex());
colorToStyle.put(rgb.toString(), style);
cell.setCellStyle(style);
}
}
}
try {
FileOutputStream out =
new FileOutputStream(new File("C:\\picture.xls"));
workbook.write(out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Карта colorToStyle используется для хранения стилей оформления ячеек.
При создании нового стиля мы связываем его с определенным цветом и каждый раз, когда закрашиваем новую ячейку, проверяем, существует ли готовый стиль для нужного цвета или его нужно создать.
И, наконец, метод преобразования цветов RGB в формат HSSFColor, используемый в Apache POI. Обратите внимание, что используется метод findSimilarColor(), который пытается автоматически найти похожий цвет в палитре.
public HSSFColor setColor(HSSFWorkbook workbook, byte r, byte g, byte b) {
HSSFPalette palette = workbook.getCustomPalette();
HSSFColor hssfColor = null;
try {
hssfColor = palette.findSimilarColor(r, g, b);
if (hssfColor == null) {
System.err.println("null " + r + " " + g + " " + b);
palette.setColorAtIndex(HSSFColor.RED.index, r, g, b);
hssfColor = palette.getColor(HSSFColor.RED.index);
}
} catch (Exception e) {
e.printStackTrace();
}
return hssfColor;
}
Результаты «творчества»:
- Значок Firefox
- Большая картина (Google Docs отображает его как 2 части, но при загрузке оказывается нормальная картинка)
- Исходники проекта на GitHub
Я не знаю, может ли Apache POI (или любая другая библиотека) работать с векторной графикой в офисных документах :( Теги: #java #apache poi #Excel #программирование #java
-
Я
19 Oct, 24 -
Советы По Управлению Вашим Доменным Именем
19 Oct, 24 -
Экология
19 Oct, 24 -
1Пароль Бесплатен
19 Oct, 24 -
Rdp Против Remotefx
19 Oct, 24 -
[Usr] Простые Декодеры
19 Oct, 24 -
Билл Гейтс Полетит В Космос.
19 Oct, 24