1 /* 2 * @(#)BMP.java - carries BMP stuff, access from 'all sides' 3 * 4 * Copyright (c) 2004-2005 by dvb.matt, All Rights Reserved. 5 * 6 * This file is part of ProjectX, a free Java based demux utility. 7 * By the authors, ProjectX is intended for educational purposes only, 8 * as a non-commercial test project. 9 * 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 */ 26 27 package net.sourceforge.dvb.projectx.subtitle; 28 29 30 //DM24042004 081.7 int02 introduced 31 32 import java.io.BufferedOutputStream; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 36 import java.util.ArrayList; 37 import java.util.Hashtable; 38 import java.util.Enumeration; 39 40 public class BMP extends Object { 41 42 private static final byte defaultHeader[] = { 43 0x42, 0x4D, //'B','M' 44 0, 0, 0, 0, // real filesize 32bit, little endian (real size*3 + header(0x36)) 45 0, 0, 0, 0, 46 0x36, 0, 0, 0, //bitmap info size 47 0x28, 0, 0, 0, 48 0, 0, 0, 0, //hsize 49 0, 0, 0, 0, //vsize 50 1, 0, //nplane 51 0x18, 0, //bitcount 24b 52 0, 0, 0, 0, //ncompr 53 0, 0, 0, 0, //image bytesize 54 (byte)0x88, 0xB, 0, 0, //nxpm 75dpi 55 (byte)0x88, 0xB, 0, 0, //nypm 75dpi 56 0, 0, 0, 0, //nclrused 57 0, 0, 0, 0 //nclrimp 58 }; 59 60 private static Hashtable bmps = new Hashtable(); 61 BMP()62 private BMP() 63 {} 64 getContents()65 public static String getContents() 66 { 67 return bmps.toString(); 68 } 69 getKeys()70 public static Enumeration getKeys() 71 { 72 return bmps.keys(); 73 } 74 isEmpty()75 public static boolean isEmpty() 76 { 77 return bmps.isEmpty(); 78 } 79 clear()80 public static void clear() 81 { 82 bmps.clear(); 83 } 84 savePixels(Bitmap bitmap)85 public static void savePixels(Bitmap bitmap) 86 { 87 bmps.put("" + bitmap.getId(), bitmap); 88 } 89 getBitmap(int id)90 public static Bitmap getBitmap(int id) 91 { 92 return (Bitmap)bmps.get("" + id); 93 } 94 littleEndian(byte[] array, int aPos, int value)95 private static void littleEndian(byte[] array, int aPos, int value) 96 { 97 for (int a=0; a<4; a++) 98 array[aPos+a] = (byte)(value>>(a*8) & 0xFF); 99 } 100 buildBMP_24bit(String outfile, String key)101 public static void buildBMP_24bit(String outfile, String key) throws IOException 102 { 103 Bitmap bitmap = (Bitmap)bmps.get(key); 104 105 if (bitmap == null) 106 return; 107 108 int width = bitmap.getWidth(); 109 int height = bitmap.getHeight(); 110 int size = 3 * width * height + height * (width & 3); 111 112 if (size == 0) 113 return; 114 115 int pixels[] = bitmap.getPixel(); 116 117 BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( outfile + ".bmp"), 65535); 118 119 byte BMPheader[] = new byte[defaultHeader.length]; 120 System.arraycopy(defaultHeader, 0, BMPheader, 0, defaultHeader.length); 121 122 byte RGB_24bit[] = new byte[3]; 123 124 littleEndian(BMPheader , 2, (0x36 + size)); 125 littleEndian(BMPheader , 18, width); 126 littleEndian(BMPheader , 22, height); 127 littleEndian(BMPheader , 34, size); 128 129 out.write(BMPheader); 130 131 for (int a = height-1; a >= 0; a--) 132 { 133 for (int b = 0; b < width; b++) 134 { 135 for (int c = 0; c < 3; c++) 136 RGB_24bit[c] = (byte)(pixels[b + a * width]>>(c * 8) & 0xFF); 137 138 out.write(RGB_24bit); 139 } 140 141 out.write(new byte[width & 3]); //padding bytes 142 } 143 144 out.flush(); 145 out.close(); 146 } 147 buildBMP_palettized(String outfile, String key, ArrayList color_table_array, int palette)148 public static String buildBMP_palettized(String outfile, String key, ArrayList color_table_array, int palette) throws IOException 149 { 150 return buildBMP_palettized(outfile, (Bitmap)bmps.get(key), color_table_array, palette); 151 } 152 buildBMP_palettized(String outfile, Bitmap bitmap, ArrayList color_table_array, int palette)153 public static String buildBMP_palettized(String outfile, Bitmap bitmap, ArrayList color_table_array, int palette) throws IOException 154 { 155 if (bitmap == null) 156 return ""; 157 158 palette = 256; //still fixed! 159 160 int width = bitmap.getWidth(); 161 int height = bitmap.getHeight(); 162 int size = palette * 4 + width * height + height * (width & 3); 163 164 if (size == 0) 165 return ""; 166 167 outfile += ".bmp"; 168 169 BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(outfile), 65535); 170 171 byte BMPheader[] = new byte[defaultHeader.length]; 172 System.arraycopy(defaultHeader, 0, BMPheader, 0, defaultHeader.length); 173 174 byte RGB_4bit = 0; // 1 pixel_index 175 176 if (palette == 256) 177 BMPheader[28] = 8; 178 else 179 BMPheader[28] = 4; 180 181 182 littleEndian(BMPheader , 2, (0x36 + size)); 183 littleEndian(BMPheader , 10, (0x36 + palette * 4)); //pixel start 184 littleEndian(BMPheader , 18, width); 185 littleEndian(BMPheader , 22, height); 186 littleEndian(BMPheader , 34, size); 187 188 out.write(BMPheader); 189 190 Object color_table[] = color_table_array.toArray(); 191 byte base_color_index[] = new byte[4]; 192 193 //paletize 256 * 4byte BGR0 indices 194 for (int a=0, color; a < palette; a++) 195 { 196 if (a < color_table.length) 197 { 198 color = 0xFFFFFF & Integer.parseInt(color_table[a].toString()); 199 200 for (int b=0; b < 3; b++) 201 base_color_index[b] = (byte)(0xFF & color>>(b<<3)); 202 } 203 204 out.write(base_color_index); 205 } 206 207 color_table = null; 208 209 int pixels[] = bitmap.getPixel(); 210 211 for (int a = height - 1; a >= 0; a--) 212 { 213 for (int b = 0, val = 0; b < width; b++) 214 { 215 out.write(0xFF & getColorIndex(pixels[b + a * width], color_table_array)); 216 } 217 218 out.write(new byte[width & 3]); //padding bytes 219 } 220 221 out.flush(); 222 out.close(); 223 224 return outfile; 225 } 226 getColorIndex(int color, ArrayList color_table)227 private static int getColorIndex(int color, ArrayList color_table) 228 { 229 String color_str = "" + color; 230 int index = color_table.indexOf(color_str); 231 232 if (index != -1) 233 return index; 234 235 return (color_table.size() - 1); 236 } 237 write_ColorTable(String outfile, ArrayList color_table_array, int palette)238 public static String write_ColorTable(String outfile, ArrayList color_table_array, int palette) throws IOException 239 { 240 Object color_table[] = color_table_array.toArray(); 241 byte base_color_index[] = new byte[4]; 242 243 outfile += ".spf"; 244 245 palette = 256; //still fixed! 246 247 BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(outfile), 65535); 248 249 //palettize number * 4byte BGR0 indices (e.g.256 or 16) 250 for (int a=0, color; a < palette; a++) 251 { 252 if (a < color_table.length) 253 { 254 color = 0xFFFFFF & Integer.parseInt(color_table[a].toString()); 255 256 for (int b=0; b < 3; b++) 257 base_color_index[b] = (byte)(0xFF & color>>(b<<3)); 258 } 259 260 out.write(base_color_index); 261 } 262 263 color_table = null; 264 265 out.flush(); 266 out.close(); 267 268 return outfile; 269 } 270 }