You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JpegImage.java 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.image;
  8. // Java
  9. import java.net.URL;
  10. import java.awt.image.ImageProducer;
  11. import java.awt.image.ColorModel;
  12. import java.awt.image.IndexColorModel;
  13. import java.io.ByteArrayOutputStream;
  14. import java.io.InputStream;
  15. // FOP
  16. import org.apache.fop.datatypes.ColorSpace;
  17. import org.apache.fop.pdf.PDFColor;
  18. import org.apache.fop.pdf.DCTFilter;
  19. import org.apache.fop.image.analyser.ImageReader;
  20. import org.apache.fop.fo.FOUserAgent;
  21. /**
  22. * FopImage object for JPEG images, Using Java native classes.
  23. * @author Eric Dalquist
  24. * @see AbstractFopImage
  25. * @see FopImage
  26. */
  27. public class JpegImage extends AbstractFopImage {
  28. boolean found_icc_profile = false;
  29. boolean found_dimensions = false;
  30. public JpegImage(URL href, ImageReader imgReader) {
  31. super(href, imgReader);
  32. }
  33. protected boolean loadBitmap(FOUserAgent ua) {
  34. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  35. ByteArrayOutputStream iccStream = new ByteArrayOutputStream();
  36. InputStream inStream;
  37. this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_UNKNOWN);
  38. byte[] readBuf = new byte[4096];
  39. int bytes_read;
  40. int index = 0;
  41. boolean cont = true;
  42. this.m_compressionType = new DCTFilter();
  43. this.m_compressionType.setApplied(true);
  44. try {
  45. inStream = this.m_href.openStream();
  46. while ((bytes_read = inStream.read(readBuf)) != -1) {
  47. baos.write(readBuf, 0, bytes_read);
  48. }
  49. } catch (java.io.IOException ex) {
  50. ua.getLogger().error("Error while loading image " +
  51. this.m_href.toString() + " : " + ex.getClass() +
  52. " - " + ex.getMessage(), ex);
  53. return false;
  54. }
  55. this.m_bitmaps = baos.toByteArray();
  56. this.m_bitsPerPixel = 8;
  57. this.m_isTransparent = false;
  58. if (this.m_bitmaps.length > (index + 2) &&
  59. uByte(this.m_bitmaps[index]) == 255 &&
  60. uByte(this.m_bitmaps[index + 1]) == 216) {
  61. index += 2;
  62. while (index < this.m_bitmaps.length && cont) {
  63. //check to be sure this is the begining of a header
  64. if (this.m_bitmaps.length > (index + 2) &&
  65. uByte(this.m_bitmaps[index]) == 255) {
  66. //192 or 194 are the header bytes that contain the jpeg width height and color depth.
  67. if (uByte(this.m_bitmaps[index + 1]) == 192 ||
  68. uByte(this.m_bitmaps[index + 1]) == 194) {
  69. this.m_height = calcBytes(this.m_bitmaps[index + 5],
  70. this.m_bitmaps[index + 6]);
  71. this.m_width = calcBytes(this.m_bitmaps[index + 7],
  72. this.m_bitmaps[index + 8]);
  73. if (this.m_bitmaps[index + 9] == 1) {
  74. this.m_colorSpace.setColorSpace(
  75. ColorSpace.DEVICE_GRAY);
  76. } else if (this.m_bitmaps[index + 9] == 3) {
  77. this.m_colorSpace.setColorSpace(
  78. ColorSpace.DEVICE_RGB);
  79. } else if (this.m_bitmaps[index + 9] == 4) {
  80. this.m_colorSpace.setColorSpace(
  81. ColorSpace.DEVICE_CMYK);
  82. }
  83. found_dimensions = true;
  84. if (found_icc_profile) {
  85. cont = false;
  86. break;
  87. }
  88. index += calcBytes(this.m_bitmaps[index + 2],
  89. this.m_bitmaps[index + 3]) + 2;
  90. } else if (uByte(this.m_bitmaps[index + 1]) ==
  91. 226 && this.m_bitmaps.length > (index + 60)) {
  92. // Check if ICC profile
  93. byte[] icc_string = new byte[11];
  94. System.arraycopy(this.m_bitmaps, index + 4,
  95. icc_string, 0, 11);
  96. if ("ICC_PROFILE".equals(new String(icc_string))) {
  97. int chunkSize = calcBytes(
  98. this.m_bitmaps[index + 2],
  99. this.m_bitmaps[index + 3]) + 2;
  100. if (iccStream.size() == 0)
  101. iccStream.write(this.m_bitmaps,
  102. index + 18, chunkSize - 20);
  103. else
  104. iccStream.write(this.m_bitmaps,
  105. index + 16, chunkSize - 18);
  106. }
  107. index += calcBytes(this.m_bitmaps[index + 2],
  108. this.m_bitmaps[index + 3]) + 2;
  109. } else {
  110. index += calcBytes(this.m_bitmaps[index + 2],
  111. this.m_bitmaps[index + 3]) + 2;
  112. }
  113. } else {
  114. cont = false;
  115. }
  116. }
  117. } else {
  118. ua.getLogger().error( "1 Error while loading image " +
  119. this.m_href.toString() +
  120. " : JpegImage - Invalid JPEG Header.");
  121. return false;
  122. }
  123. if (iccStream.size() > 0) {
  124. byte[] align = new byte[((iccStream.size()) % 8) + 8];
  125. try {
  126. iccStream.write(align);
  127. } catch (Exception e) {
  128. ua.getLogger().error( "1 Error while loading image " +
  129. this.m_href.toString() + " : " +
  130. e.getMessage(), e);
  131. return false;
  132. }
  133. this.m_colorSpace.setICCProfile(iccStream.toByteArray());
  134. }
  135. return true;
  136. }
  137. private int calcBytes(byte bOne, byte bTwo) {
  138. return (uByte(bOne) * 256) + uByte(bTwo);
  139. }
  140. private int uByte(byte bIn) {
  141. if (bIn < 0) {
  142. return 256 + bIn;
  143. } else {
  144. return bIn;
  145. }
  146. }
  147. }