1 50 51 package com.lowagie.text.pdf.codec.wmf; 52 import java.awt.Color ; 53 import java.awt.Point ; 54 import java.io.ByteArrayInputStream ; 55 import java.io.ByteArrayOutputStream ; 56 import java.io.IOException ; 57 import java.io.InputStream ; 58 import java.io.OutputStream ; 59 import java.io.UnsupportedEncodingException ; 60 import java.util.ArrayList ; 61 62 import com.lowagie.text.DocumentException; 63 import com.lowagie.text.Image; 64 import com.lowagie.text.pdf.BaseFont; 65 import com.lowagie.text.pdf.PdfContentByte; 66 import com.lowagie.text.pdf.codec.BmpImage; 67 68 public class MetaDo { 69 70 public static final int META_SETBKCOLOR = 0x0201; 71 public static final int META_SETBKMODE = 0x0102; 72 public static final int META_SETMAPMODE = 0x0103; 73 public static final int META_SETROP2 = 0x0104; 74 public static final int META_SETRELABS = 0x0105; 75 public static final int META_SETPOLYFILLMODE = 0x0106; 76 public static final int META_SETSTRETCHBLTMODE = 0x0107; 77 public static final int META_SETTEXTCHAREXTRA = 0x0108; 78 public static final int META_SETTEXTCOLOR = 0x0209; 79 public static final int META_SETTEXTJUSTIFICATION = 0x020A; 80 public static final int META_SETWINDOWORG = 0x020B; 81 public static final int META_SETWINDOWEXT = 0x020C; 82 public static final int META_SETVIEWPORTORG = 0x020D; 83 public static final int META_SETVIEWPORTEXT = 0x020E; 84 public static final int META_OFFSETWINDOWORG = 0x020F; 85 public static final int META_SCALEWINDOWEXT = 0x0410; 86 public static final int META_OFFSETVIEWPORTORG = 0x0211; 87 public static final int META_SCALEVIEWPORTEXT = 0x0412; 88 public static final int META_LINETO = 0x0213; 89 public static final int META_MOVETO = 0x0214; 90 public static final int META_EXCLUDECLIPRECT = 0x0415; 91 public static final int META_INTERSECTCLIPRECT = 0x0416; 92 public static final int META_ARC = 0x0817; 93 public static final int META_ELLIPSE = 0x0418; 94 public static final int META_FLOODFILL = 0x0419; 95 public static final int META_PIE = 0x081A; 96 public static final int META_RECTANGLE = 0x041B; 97 public static final int META_ROUNDRECT = 0x061C; 98 public static final int META_PATBLT = 0x061D; 99 public static final int META_SAVEDC = 0x001E; 100 public static final int META_SETPIXEL = 0x041F; 101 public static final int META_OFFSETCLIPRGN = 0x0220; 102 public static final int META_TEXTOUT = 0x0521; 103 public static final int META_BITBLT = 0x0922; 104 public static final int META_STRETCHBLT = 0x0B23; 105 public static final int META_POLYGON = 0x0324; 106 public static final int META_POLYLINE = 0x0325; 107 public static final int META_ESCAPE = 0x0626; 108 public static final int META_RESTOREDC = 0x0127; 109 public static final int META_FILLREGION = 0x0228; 110 public static final int META_FRAMEREGION = 0x0429; 111 public static final int META_INVERTREGION = 0x012A; 112 public static final int META_PAINTREGION = 0x012B; 113 public static final int META_SELECTCLIPREGION = 0x012C; 114 public static final int META_SELECTOBJECT = 0x012D; 115 public static final int META_SETTEXTALIGN = 0x012E; 116 public static final int META_CHORD = 0x0830; 117 public static final int META_SETMAPPERFLAGS = 0x0231; 118 public static final int META_EXTTEXTOUT = 0x0a32; 119 public static final int META_SETDIBTODEV = 0x0d33; 120 public static final int META_SELECTPALETTE = 0x0234; 121 public static final int META_REALIZEPALETTE = 0x0035; 122 public static final int META_ANIMATEPALETTE = 0x0436; 123 public static final int META_SETPALENTRIES = 0x0037; 124 public static final int META_POLYPOLYGON = 0x0538; 125 public static final int META_RESIZEPALETTE = 0x0139; 126 public static final int META_DIBBITBLT = 0x0940; 127 public static final int META_DIBSTRETCHBLT = 0x0b41; 128 public static final int META_DIBCREATEPATTERNBRUSH = 0x0142; 129 public static final int META_STRETCHDIB = 0x0f43; 130 public static final int META_EXTFLOODFILL = 0x0548; 131 public static final int META_DELETEOBJECT = 0x01f0; 132 public static final int META_CREATEPALETTE = 0x00f7; 133 public static final int META_CREATEPATTERNBRUSH = 0x01F9; 134 public static final int META_CREATEPENINDIRECT = 0x02FA; 135 public static final int META_CREATEFONTINDIRECT = 0x02FB; 136 public static final int META_CREATEBRUSHINDIRECT = 0x02FC; 137 public static final int META_CREATEREGION = 0x06FF; 138 139 public PdfContentByte cb; 140 public InputMeta in; 141 int left; 142 int top; 143 int right; 144 int bottom; 145 int inch; 146 MetaState state = new MetaState(); 147 148 public MetaDo(InputStream in, PdfContentByte cb) { 149 this.cb = cb; 150 this.in = new InputMeta(in); 151 } 152 153 public void readAll() throws IOException , DocumentException{ 154 if (in.readInt() != 0x9AC6CDD7) { 155 throw new DocumentException("Not a placeable windows metafile"); 156 } 157 in.readWord(); 158 left = in.readShort(); 159 top = in.readShort(); 160 right = in.readShort(); 161 bottom = in.readShort(); 162 inch = in.readWord(); 163 state.setScalingX((float)(right - left) / (float)inch * 72f); 164 state.setScalingY((float)(bottom - top) / (float)inch * 72f); 165 state.setOffsetWx(left); 166 state.setOffsetWy(top); 167 state.setExtentWx(right - left); 168 state.setExtentWy(bottom - top); 169 in.readInt(); 170 in.readWord(); 171 in.skip(18); 172 173 int tsize; 174 int function; 175 cb.setLineCap(1); 176 cb.setLineJoin(1); 177 for (;;) { 178 int lenMarker = in.getLength(); 179 tsize = in.readInt(); 180 if (tsize < 3) 181 break; 182 function = in.readWord(); 183 switch (function) { 184 case 0: 185 break; 186 case META_CREATEPALETTE: 187 case META_CREATEREGION: 188 case META_DIBCREATEPATTERNBRUSH: 189 state.addMetaObject(new MetaObject()); 190 break; 191 case META_CREATEPENINDIRECT: 192 { 193 MetaPen pen = new MetaPen(); 194 pen.init(in); 195 state.addMetaObject(pen); 196 break; 197 } 198 case META_CREATEBRUSHINDIRECT: 199 { 200 MetaBrush brush = new MetaBrush(); 201 brush.init(in); 202 state.addMetaObject(brush); 203 break; 204 } 205 case META_CREATEFONTINDIRECT: 206 { 207 MetaFont font = new MetaFont(); 208 font.init(in); 209 state.addMetaObject(font); 210 break; 211 } 212 case META_SELECTOBJECT: 213 { 214 int idx = in.readWord(); 215 state.selectMetaObject(idx, cb); 216 break; 217 } 218 case META_DELETEOBJECT: 219 { 220 int idx = in.readWord(); 221 state.deleteMetaObject(idx); 222 break; 223 } 224 case META_SAVEDC: 225 state.saveState(cb); 226 break; 227 case META_RESTOREDC: 228 { 229 int idx = in.readShort(); 230 state.restoreState(idx, cb); 231 break; 232 } 233 case META_SETWINDOWORG: 234 state.setOffsetWy(in.readShort()); 235 state.setOffsetWx(in.readShort()); 236 break; 237 case META_SETWINDOWEXT: 238 state.setExtentWy(in.readShort()); 239 state.setExtentWx(in.readShort()); 240 break; 241 case META_MOVETO: 242 { 243 int y = in.readShort(); 244 Point p = new Point (in.readShort(), y); 245 state.setCurrentPoint(p); 246 break; 247 } 248 case META_LINETO: 249 { 250 int y = in.readShort(); 251 int x = in.readShort(); 252 Point p = state.getCurrentPoint(); 253 cb.moveTo(state.transformX(p.x), state.transformY(p.y)); 254 cb.lineTo(state.transformX(x), state.transformY(y)); 255 cb.stroke(); 256 state.setCurrentPoint(new Point (x, y)); 257 break; 258 } 259 case META_POLYLINE: 260 { 261 state.setLineJoinPolygon(cb); 262 int len = in.readWord(); 263 int x = in.readShort(); 264 int y = in.readShort(); 265 cb.moveTo(state.transformX(x), state.transformY(y)); 266 for (int k = 1; k < len; ++k) { 267 x = in.readShort(); 268 y = in.readShort(); 269 cb.lineTo(state.transformX(x), state.transformY(y)); 270 } 271 cb.stroke(); 272 break; 273 } 274 case META_POLYGON: 275 { 276 if (isNullStrokeFill(false)) 277 break; 278 int len = in.readWord(); 279 int sx = in.readShort(); 280 int sy = in.readShort(); 281 cb.moveTo(state.transformX(sx), state.transformY(sy)); 282 for (int k = 1; k < len; ++k) { 283 int x = in.readShort(); 284 int y = in.readShort(); 285 cb.lineTo(state.transformX(x), state.transformY(y)); 286 } 287 cb.lineTo(state.transformX(sx), state.transformY(sy)); 288 strokeAndFill(); 289 break; 290 } 291 case META_POLYPOLYGON: 292 { 293 if (isNullStrokeFill(false)) 294 break; 295 int numPoly = in.readWord(); 296 int lens[] = new int[numPoly]; 297 for (int k = 0; k < lens.length; ++k) 298 lens[k] = in.readWord(); 299 for (int j = 0; j < lens.length; ++j) { 300 int len = lens[j]; 301 int sx = in.readShort(); 302 int sy = in.readShort(); 303 cb.moveTo(state.transformX(sx), state.transformY(sy)); 304 for (int k = 1; k < len; ++k) { 305 int x = in.readShort(); 306 int y = in.readShort(); 307 cb.lineTo(state.transformX(x), state.transformY(y)); 308 } 309 cb.lineTo(state.transformX(sx), state.transformY(sy)); 310 } 311 strokeAndFill(); 312 break; 313 } 314 case META_ELLIPSE: 315 { 316 if (isNullStrokeFill(state.getLineNeutral())) 317 break; 318 int b = in.readShort(); 319 int r = in.readShort(); 320 int t = in.readShort(); 321 int l = in.readShort(); 322 cb.arc(state.transformX(l), state.transformY(b), state.transformX(r), state.transformY(t), 0, 360); 323 strokeAndFill(); 324 break; 325 } 326 case META_ARC: 327 { 328 if (isNullStrokeFill(state.getLineNeutral())) 329 break; 330 float yend = state.transformY(in.readShort()); 331 float xend = state.transformX(in.readShort()); 332 float ystart = state.transformY(in.readShort()); 333 float xstart = state.transformX(in.readShort()); 334 float b = state.transformY(in.readShort()); 335 float r = state.transformX(in.readShort()); 336 float t = state.transformY(in.readShort()); 337 float l = state.transformX(in.readShort()); 338 float cx = (r + l) / 2; 339 float cy = (t + b) / 2; 340 float arc1 = getArc(cx, cy, xstart, ystart); 341 float arc2 = getArc(cx, cy, xend, yend); 342 arc2 -= arc1; 343 if (arc2 <= 0) 344 arc2 += 360; 345 cb.arc(l, b, r, t, arc1, arc2); 346 cb.stroke(); 347 break; 348 } 349 case META_PIE: 350 { 351 if (isNullStrokeFill(state.getLineNeutral())) 352 break; 353 float yend = state.transformY(in.readShort()); 354 float xend = state.transformX(in.readShort()); 355 float ystart = state.transformY(in.readShort()); 356 float xstart = state.transformX(in.readShort()); 357 float b = state.transformY(in.readShort()); 358 float r = state.transformX(in.readShort()); 359 float t = state.transformY(in.readShort()); 360 float l = state.transformX(in.readShort()); 361 float cx = (r + l) / 2; 362 float cy = (t + b) / 2; 363 float arc1 = getArc(cx, cy, xstart, ystart); 364 float arc2 = getArc(cx, cy, xend, yend); 365 arc2 -= arc1; 366 if (arc2 <= 0) 367 arc2 += 360; 368 ArrayList ar = PdfContentByte.bezierArc(l, b, r, t, arc1, arc2); 369 if (ar.isEmpty()) 370 break; 371 float pt[] = (float [])ar.get(0); 372 cb.moveTo(cx, cy); 373 cb.lineTo(pt[0], pt[1]); 374 for (int k = 0; k < ar.size(); ++k) { 375 pt = (float [])ar.get(k); 376 cb.curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]); 377 } 378 cb.lineTo(cx, cy); 379 strokeAndFill(); 380 break; 381 } 382 case META_CHORD: 383 { 384 if (isNullStrokeFill(state.getLineNeutral())) 385 break; 386 float yend = state.transformY(in.readShort()); 387 float xend = state.transformX(in.readShort()); 388 float ystart = state.transformY(in.readShort()); 389 float xstart = state.transformX(in.readShort()); 390 float b = state.transformY(in.readShort()); 391 float r = state.transformX(in.readShort()); 392 float t = state.transformY(in.readShort()); 393 float l = state.transformX(in.readShort()); 394 float cx = (r + l) / 2; 395 float cy = (t + b) / 2; 396 float arc1 = getArc(cx, cy, xstart, ystart); 397 float arc2 = getArc(cx, cy, xend, yend); 398 arc2 -= arc1; 399 if (arc2 <= 0) 400 arc2 += 360; 401 ArrayList ar = PdfContentByte.bezierArc(l, b, r, t, arc1, arc2); 402 if (ar.isEmpty()) 403 break; 404 float pt[] = (float [])ar.get(0); 405 cx = pt[0]; 406 cy = pt[1]; 407 cb.moveTo(cx, cy); 408 for (int k = 0; k < ar.size(); ++k) { 409 pt = (float [])ar.get(k); 410 cb.curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]); 411 } 412 cb.lineTo(cx, cy); 413 strokeAndFill(); 414 break; 415 } 416 case META_RECTANGLE: 417 { 418 if (isNullStrokeFill(true)) 419 break; 420 float b = state.transformY(in.readShort()); 421 float r = state.transformX(in.readShort()); 422 float t = state.transformY(in.readShort()); 423 float l = state.transformX(in.readShort()); 424 cb.rectangle(l, b, r - l, t - b); 425 strokeAndFill(); 426 break; 427 } 428 case META_ROUNDRECT: 429 { 430 if (isNullStrokeFill(true)) 431 break; 432 float h = state.transformY(0) - state.transformY(in.readShort()); 433 float w = state.transformX(in.readShort()) - state.transformX(0); 434 float b = state.transformY(in.readShort()); 435 float r = state.transformX(in.readShort()); 436 float t = state.transformY(in.readShort()); 437 float l = state.transformX(in.readShort()); 438 cb.roundRectangle(l, b, r - l, t - b, (h + w) / 4); 439 strokeAndFill(); 440 break; 441 } 442 case META_INTERSECTCLIPRECT: 443 { 444 float b = state.transformY(in.readShort()); 445 float r = state.transformX(in.readShort()); 446 float t = state.transformY(in.readShort()); 447 float l = state.transformX(in.readShort()); 448 cb.rectangle(l, b, r - l, t - b); 449 cb.eoClip(); 450 cb.newPath(); 451 break; 452 } 453 case META_EXTTEXTOUT: 454 { 455 int y = in.readShort(); 456 int x = in.readShort(); 457 int count = in.readWord(); 458 int flag = in.readWord(); 459 int x1 = 0; 460 int y1 = 0; 461 int x2 = 0; 462 int y2 = 0; 463 if ((flag & (MetaFont.ETO_CLIPPED | MetaFont.ETO_OPAQUE)) != 0) { 464 x1 = in.readShort(); 465 y1 = in.readShort(); 466 x2 = in.readShort(); 467 y2 = in.readShort(); 468 } 469 byte text[] = new byte[count]; 470 int k; 471 for (k = 0; k < count; ++k) { 472 byte c = (byte)in.readByte(); 473 if (c == 0) 474 break; 475 text[k] = c; 476 } 477 String s; 478 try { 479 s = new String (text, 0, k, "Cp1252"); 480 } 481 catch (UnsupportedEncodingException e) { 482 s = new String (text, 0, k); 483 } 484 outputText(x, y, flag, x1, y1, x2, y2, s); 485 break; 486 } 487 case META_TEXTOUT: 488 { 489 int count = in.readWord(); 490 byte text[] = new byte[count]; 491 int k; 492 for (k = 0; k < count; ++k) { 493 byte c = (byte)in.readByte(); 494 if (c == 0) 495 break; 496 text[k] = c; 497 } 498 String s; 499 try { 500 s = new String (text, 0, k, "Cp1252"); 501 } 502 catch (UnsupportedEncodingException e) { 503 s = new String (text, 0, k); 504 } 505 count = (count + 1) & 0xfffe; 506 in.skip(count - k); 507 int y = in.readShort(); 508 int x = in.readShort(); 509 outputText(x, y, 0, 0, 0, 0, 0, s); 510 break; 511 } 512 case META_SETBKCOLOR: 513 state.setCurrentBackgroundColor(in.readColor()); 514 break; 515 case META_SETTEXTCOLOR: 516 state.setCurrentTextColor(in.readColor()); 517 break; 518 case META_SETTEXTALIGN: 519 state.setTextAlign(in.readWord()); 520 break; 521 case META_SETBKMODE: 522 state.setBackgroundMode(in.readWord()); 523 break; 524 case META_SETPOLYFILLMODE: 525 state.setPolyFillMode(in.readWord()); 526 break; 527 case META_SETPIXEL: 528 { 529 Color color = in.readColor(); 530 int y = in.readShort(); 531 int x = in.readShort(); 532 cb.saveState(); 533 cb.setColorFill(color); 534 cb.rectangle(state.transformX(x), state.transformY(y), .2f, .2f); 535 cb.fill(); 536 cb.restoreState(); 537 break; 538 } 539 case META_DIBSTRETCHBLT: 540 case META_STRETCHDIB: { 541 int rop = in.readInt(); 542 if (function == META_STRETCHDIB) { 543 in.readWord(); 544 } 545 int srcHeight = in.readShort(); 546 int srcWidth = in.readShort(); 547 int ySrc = in.readShort(); 548 int xSrc = in.readShort(); 549 float destHeight = state.transformY(in.readShort()) - state.transformY(0); 550 float destWidth = state.transformX(in.readShort()) - state.transformX(0); 551 float yDest = state.transformY(in.readShort()); 552 float xDest = state.transformX(in.readShort()); 553 byte b[] = new byte[(tsize * 2) - (in.getLength() - lenMarker)]; 554 for (int k = 0; k < b.length; ++k) 555 b[k] = (byte)in.readByte(); 556 try { 557 ByteArrayInputStream inb = new ByteArrayInputStream (b); 558 Image bmp = BmpImage.getImage(inb, true, b.length); 559 cb.saveState(); 560 cb.rectangle(xDest, yDest, destWidth, destHeight); 561 cb.clip(); 562 cb.newPath(); 563 bmp.scaleAbsolute(destWidth * bmp.getWidth() / srcWidth, -destHeight * bmp.getHeight() / srcHeight); 564 bmp.setAbsolutePosition(xDest - destWidth * xSrc / srcWidth, yDest + destHeight * ySrc / srcHeight - bmp.getScaledHeight()); 565 cb.addImage(bmp); 566 cb.restoreState(); 567 } 568 catch (Exception e) { 569 } 571 break; 572 } 573 } 574 in.skip((tsize * 2) - (in.getLength() - lenMarker)); 575 } 576 state.cleanup(cb); 577 } 578 579 public void outputText(int x, int y, int flag, int x1, int y1, int x2, int y2, String text) { 580 MetaFont font = state.getCurrentFont(); 581 float refX = state.transformX(x); 582 float refY = state.transformY(y); 583 float angle = state.transformAngle(font.getAngle()); 584 float sin = (float)Math.sin(angle); 585 float cos = (float)Math.cos(angle); 586 float fontSize = font.getFontSize(state); 587 BaseFont bf = font.getFont(); 588 int align = state.getTextAlign(); 589 float textWidth = bf.getWidthPoint(text, fontSize); 590 float tx = 0; 591 float ty = 0; 592 float descender = bf.getFontDescriptor(BaseFont.DESCENT, fontSize); 593 float ury = bf.getFontDescriptor(BaseFont.BBOXURY, fontSize); 594 cb.saveState(); 595 cb.concatCTM(cos, sin, -sin, cos, refX, refY); 596 if ((align & MetaState.TA_CENTER) == MetaState.TA_CENTER) 597 tx = -textWidth / 2; 598 else if ((align & MetaState.TA_RIGHT) == MetaState.TA_RIGHT) 599 tx = -textWidth; 600 if ((align & MetaState.TA_BASELINE) == MetaState.TA_BASELINE) 601 ty = 0; 602 else if ((align & MetaState.TA_BOTTOM) == MetaState.TA_BOTTOM) 603 ty = -descender; 604 else 605 ty = -ury; 606 Color textColor; 607 if (state.getBackgroundMode() == MetaState.OPAQUE) { 608 textColor = state.getCurrentBackgroundColor(); 609 cb.setColorFill(textColor); 610 cb.rectangle(tx, ty + descender, textWidth, ury - descender); 611 cb.fill(); 612 } 613 textColor = state.getCurrentTextColor(); 614 cb.setColorFill(textColor); 615 cb.beginText(); 616 cb.setFontAndSize(bf, fontSize); 617 cb.setTextMatrix(tx, ty); 618 cb.showText(text); 619 cb.endText(); 620 if (font.isUnderline()) { 621 cb.rectangle(tx, ty - fontSize / 4, textWidth, fontSize / 15); 622 cb.fill(); 623 } 624 if (font.isStrikeout()) { 625 cb.rectangle(tx, ty + fontSize / 3, textWidth, fontSize / 15); 626 cb.fill(); 627 } 628 cb.restoreState(); 629 } 630 631 public boolean isNullStrokeFill(boolean isRectangle) { 632 MetaPen pen = state.getCurrentPen(); 633 MetaBrush brush = state.getCurrentBrush(); 634 boolean noPen = (pen.getStyle() == MetaPen.PS_NULL); 635 int style = brush.getStyle(); 636 boolean isBrush = (style == MetaBrush.BS_SOLID || (style == MetaBrush.BS_HATCHED && state.getBackgroundMode() == MetaState.OPAQUE)); 637 boolean result = noPen && !isBrush; 638 if (!noPen) { 639 if (isRectangle) 640 state.setLineJoinRectangle(cb); 641 else 642 state.setLineJoinPolygon(cb); 643 } 644 return result; 645 } 646 647 public void strokeAndFill(){ 648 MetaPen pen = state.getCurrentPen(); 649 MetaBrush brush = state.getCurrentBrush(); 650 int penStyle = pen.getStyle(); 651 int brushStyle = brush.getStyle(); 652 if (penStyle == MetaPen.PS_NULL) { 653 cb.closePath(); 654 if (state.getPolyFillMode() == MetaState.ALTERNATE) { 655 cb.eoFill(); 656 } 657 else { 658 cb.fill(); 659 } 660 } 661 else { 662 boolean isBrush = (brushStyle == MetaBrush.BS_SOLID || (brushStyle == MetaBrush.BS_HATCHED && state.getBackgroundMode() == MetaState.OPAQUE)); 663 if (isBrush) { 664 if (state.getPolyFillMode() == MetaState.ALTERNATE) 665 cb.closePathEoFillStroke(); 666 else 667 cb.closePathFillStroke(); 668 } 669 else { 670 cb.closePathStroke(); 671 } 672 } 673 } 674 675 static float getArc(float xCenter, float yCenter, float xDot, float yDot) { 676 double s = Math.atan2(yDot - yCenter, xDot - xCenter); 677 if (s < 0) 678 s += Math.PI * 2; 679 return (float)(s / Math.PI * 180); 680 } 681 682 public static byte[] wrapBMP(Image image) throws IOException { 683 if (image.getOriginalType() != Image.ORIGINAL_BMP) 684 throw new IOException ("Only BMP can be wrapped in WMF."); 685 InputStream imgIn; 686 byte data[] = null; 687 if (image.getOriginalData() == null) { 688 imgIn = image.getUrl().openStream(); 689 ByteArrayOutputStream out = new ByteArrayOutputStream (); 690 int b = 0; 691 while ((b = imgIn.read()) != -1) 692 out.write(b); 693 imgIn.close(); 694 data = out.toByteArray(); 695 } 696 else 697 data = image.getOriginalData(); 698 int sizeBmpWords = (data.length - 14 + 1) >>> 1; 699 ByteArrayOutputStream os = new ByteArrayOutputStream (); 700 writeWord(os, 1); 702 writeWord(os, 9); 703 writeWord(os, 0x0300); 704 writeDWord(os, 9 + 4 + 5 + 5 + (13 + sizeBmpWords) + 3); writeWord(os, 1); 706 writeDWord(os, 14 + sizeBmpWords); writeWord(os, 0); 708 writeDWord(os, 4); 710 writeWord(os, META_SETMAPMODE); 711 writeWord(os, 8); 712 713 writeDWord(os, 5); 714 writeWord(os, META_SETWINDOWORG); 715 writeWord(os, 0); 716 writeWord(os, 0); 717 718 writeDWord(os, 5); 719 writeWord(os, META_SETWINDOWEXT); 720 writeWord(os, (int)image.getHeight()); 721 writeWord(os, (int)image.getWidth()); 722 723 writeDWord(os, 13 + sizeBmpWords); 724 writeWord(os, META_DIBSTRETCHBLT); 725 writeDWord(os, 0x00cc0020); 726 writeWord(os, (int)image.getHeight()); 727 writeWord(os, (int)image.getWidth()); 728 writeWord(os, 0); 729 writeWord(os, 0); 730 writeWord(os, (int)image.getHeight()); 731 writeWord(os, (int)image.getWidth()); 732 writeWord(os, 0); 733 writeWord(os, 0); 734 os.write(data, 14, data.length - 14); 735 if ((data.length & 1) == 1) 736 os.write(0); 737 753 writeDWord(os, 3); 754 writeWord(os, 0); 755 os.close(); 756 return os.toByteArray(); 757 } 758 759 public static void writeWord(OutputStream os, int v) throws IOException { 760 os.write(v & 0xff); 761 os.write((v >>> 8) & 0xff); 762 } 763 764 public static void writeDWord(OutputStream os, int v) throws IOException { 765 writeWord(os, v & 0xffff); 766 writeWord(os, (v >>> 16) & 0xffff); 767 } 768 } | Popular Tags |