しばらく前、ベクター機能を使用してMS Excelで絵を描く
アーティストに関する記事がhabrに掲載されました。 しかし、そのずっと前に、同じExcelで驚異的なビットマップ図面についての話を見つけました。そのアイデアはピクセルアートに基づいています。 つまり 誰かが単にセルのサイズを縮小し、色の塗りつぶしを使用して一種のモザイクを作成します。 それは確かに品質のベクトル図面に到達しませんが、それは非常に印象的に見えます。
そのような写真を見たとき、もちろん、誰かがそれらを手動で作成するのに十分な忍耐力を持っていることを疑い、「事務」を自動化する方法を探すことにしました。 専用のMicrosoft Office形式で動作するように設計され
たApache POIライブラリが使用されている場合、タスクはJava言語での実装が簡単であることが判明しました。 カットの下の詳細。
だから私たちが持っているもの。 私は、最も一般的なJPGイメージ(または原則として、他の一般的な形式)をExcelドキュメントに変換するアプリケーションを作成するタスクを自分で設定しました。 すぐに既存の制限に言及する価値があります:
「画像」の幅は255ポイント(シート上の列の最大数)を超えてはなりません。
デザインスタイルの最大数(この場合、これは色の数です)は4000です
したがって、最初に画像を見つけて準備する(サイズと色深度を減らす)か、プログラムで行う必要があります。 2番目の方法に進みます:)

最初に、1つのメソッドを含むプログラムの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); } }
もちろん、悲惨でハードコードですが、デモンストレーションのために行います。
ファイルから写真を読み取るためのクラスを検討してください。 実際に画像を読み取るためのメソッドが含まれ、ポイントの色の3つのコンポーネントに関する情報を格納するRGBColorタイプのオブジェクトを含むマップの形式で結果を返します。
public Map<String, Object[]> read(String fileName) { File file = new File(fileName); BufferedImage source, image;
画像のサイズを変更する方法もあります。
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; }
そして、色を減らす方法(私は8ビット色を使用します、他のオプション
については、ソースを参照してください ):
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カラーをApache POIで使用されるHSSFColor形式に変換する方法。 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; }
「創造性」の結果:
もちろん、このようなモザイクは傑作とはほど遠いですが、画像とそのサイズに適切な色を選択すれば、かなり素晴らしい「絵」を得ることができます。 Apache POI(またはその他)がオフィス文書のベクター描画で動作できるかどうかはわかりません:(