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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. import java.awt.color.ColorSpace;
  16. import java.awt.color.ICC_Profile;
  17. import java.awt.color.ICC_ColorSpace;
  18. // FOP
  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. ICC_Profile iccProfile = null;
  29. boolean found_icc_profile = false;
  30. boolean found_dimensions = false;
  31. public JpegImage(URL href, FopImage.ImageInfo imgReader) {
  32. super(href, imgReader);
  33. }
  34. protected boolean loadOriginalData(FOUserAgent ua) {
  35. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  36. ByteArrayOutputStream iccStream = new ByteArrayOutputStream();
  37. InputStream inStream;
  38. byte[] readBuf = new byte[4096];
  39. int bytes_read;
  40. int index = 0;
  41. boolean cont = true;
  42. try {
  43. inStream = this.m_href.openStream();
  44. while ((bytes_read = inStream.read(readBuf)) != -1) {
  45. baos.write(readBuf, 0, bytes_read);
  46. }
  47. } catch (java.io.IOException ex) {
  48. ua.getLogger().error("Error while loading image " +
  49. this.m_href.toString() + " : " + ex.getClass() +
  50. " - " + ex.getMessage(), ex);
  51. return false;
  52. }
  53. this.m_bitmaps = baos.toByteArray();
  54. this.m_bitsPerPixel = 8;
  55. this.m_isTransparent = false;
  56. if (this.m_bitmaps.length > (index + 2) &&
  57. uByte(this.m_bitmaps[index]) == 255 &&
  58. uByte(this.m_bitmaps[index + 1]) == 216) {
  59. index += 2;
  60. while (index < this.m_bitmaps.length && cont) {
  61. //check to be sure this is the begining of a header
  62. if (this.m_bitmaps.length > (index + 2) &&
  63. uByte(this.m_bitmaps[index]) == 255) {
  64. //192 or 194 are the header bytes that contain the jpeg width height and color depth.
  65. if (uByte(this.m_bitmaps[index + 1]) == 192 ||
  66. uByte(this.m_bitmaps[index + 1]) == 194) {
  67. this.m_height = calcBytes(this.m_bitmaps[index + 5],
  68. this.m_bitmaps[index + 6]);
  69. this.m_width = calcBytes(this.m_bitmaps[index + 7],
  70. this.m_bitmaps[index + 8]);
  71. if (this.m_bitmaps[index + 9] == 1) {
  72. this.m_colorSpace = ColorSpace.getInstance(
  73. ColorSpace.CS_GRAY);
  74. } else if (this.m_bitmaps[index + 9] == 3) {
  75. this.m_colorSpace = ColorSpace.getInstance(
  76. ColorSpace.CS_LINEAR_RGB);
  77. } else if (this.m_bitmaps[index + 9] == 4) {
  78. // howto create CMYK color space
  79. this.m_colorSpace = ColorSpace.getInstance(
  80. ColorSpace.CS_CIEXYZ);
  81. } else {
  82. ua.getLogger().error("Unknown ColorSpace for image: "
  83. + this.m_href.toString());
  84. return false;
  85. }
  86. found_dimensions = true;
  87. if (found_icc_profile) {
  88. cont = false;
  89. break;
  90. }
  91. index += calcBytes(this.m_bitmaps[index + 2],
  92. this.m_bitmaps[index + 3]) + 2;
  93. } else if (uByte(this.m_bitmaps[index + 1]) ==
  94. 226 && this.m_bitmaps.length > (index + 60)) {
  95. // Check if ICC profile
  96. byte[] icc_string = new byte[11];
  97. System.arraycopy(this.m_bitmaps, index + 4,
  98. icc_string, 0, 11);
  99. if ("ICC_PROFILE".equals(new String(icc_string))) {
  100. int chunkSize = calcBytes(
  101. this.m_bitmaps[index + 2],
  102. this.m_bitmaps[index + 3]) + 2;
  103. if (iccStream.size() == 0)
  104. iccStream.write(this.m_bitmaps,
  105. index + 18, chunkSize - 20);
  106. else
  107. iccStream.write(this.m_bitmaps,
  108. index + 16, chunkSize - 18);
  109. }
  110. index += calcBytes(this.m_bitmaps[index + 2],
  111. this.m_bitmaps[index + 3]) + 2;
  112. } else {
  113. index += calcBytes(this.m_bitmaps[index + 2],
  114. this.m_bitmaps[index + 3]) + 2;
  115. }
  116. } else {
  117. cont = false;
  118. }
  119. }
  120. } else {
  121. ua.getLogger().error( "1 Error while loading image " +
  122. this.m_href.toString() +
  123. " : JpegImage - Invalid JPEG Header.");
  124. return false;
  125. }
  126. if (iccStream.size() > 0) {
  127. byte[] align = new byte[((iccStream.size()) % 8) + 8];
  128. try {
  129. iccStream.write(align);
  130. } catch (Exception e) {
  131. ua.getLogger().error( "1 Error while loading image " +
  132. this.m_href.toString() + " : " +
  133. e.getMessage(), e);
  134. return false;
  135. }
  136. iccProfile = ICC_Profile.getInstance(iccStream.toByteArray());
  137. } else if(this.m_colorSpace == null) {
  138. ua.getLogger().error("ColorSpace not specified for image: "
  139. + this.m_href.toString());
  140. return false;
  141. }
  142. return true;
  143. }
  144. public ICC_Profile getICCProfile() {
  145. return iccProfile;
  146. }
  147. private int calcBytes(byte bOne, byte bTwo) {
  148. return (uByte(bOne) * 256) + uByte(bTwo);
  149. }
  150. private int uByte(byte bIn) {
  151. if (bIn < 0) {
  152. return 256 + bIn;
  153. } else {
  154. return bIn;
  155. }
  156. }
  157. }