Ejemplo n.º 1
0
  /* this is changed
  public void run() {
  */
  public void produceImage() throws IOException, ImageFormatException {
    /* this is not needed
    ImageConsumer t = target;
    if(t!=null) try {
    */
    try {
      for (int i = 0; i < signature.length; i++)
        if ((signature[i] & 0xFF) != underlyingInputStream.read())
          throw new PNGException("Chunk signature mismatch");

      InputStream is =
          new BufferedInputStream(new InflaterInputStream(inputStream, new Inflater()));

      getData();

      byte[] bPixels = null;
      int[] wPixels = null;
      int pixSize = width;
      int rowStride;
      int logDepth = 0;
      switch (bitDepth) {
        case 1:
          logDepth = 0;
          break;
        case 2:
          logDepth = 1;
          break;
        case 4:
          logDepth = 2;
          break;
        case 8:
          logDepth = 3;
          break;
        case 16:
          logDepth = 4;
          break;
        default:
          throw new PNGException("invalid depth");
      }
      if (interlaceMethod != 0) {
        pixSize *= height;
        rowStride = width;
      } else rowStride = 0;
      int combinedType = colorType | (bitDepth << 3);
      int bitMask = (1 << (bitDepth >= 8 ? 8 : bitDepth)) - 1;
      // Figure out the color model
      switch (colorType) {
        case COLOR | PALETTE:
        case COLOR | PALETTE | ALPHA:
          if (red_map == null) throw new PNGException("palette expected");
          if (alpha_map == null)
            cm = new IndexColorModel(bitDepth, red_map.length, red_map, green_map, blue_map);
          else
            cm =
                new IndexColorModel(
                    bitDepth, red_map.length, red_map, green_map, blue_map, alpha_map);
          bPixels = new byte[pixSize];
          break;
        case GRAY:
          {
            int llog = logDepth >= 4 ? 3 : logDepth;
            if ((cm = greyModels[llog]) == null) {
              int size = 1 << (1 << llog);

              byte ramp[] = new byte[size];
              for (int i = 0; i < size; i++) ramp[i] = (byte) (255 * i / (size - 1));

              if (transparentPixel == -1) {
                cm = new IndexColorModel(bitDepth, ramp.length, ramp, ramp, ramp);
              } else {
                cm =
                    new IndexColorModel(
                        bitDepth, ramp.length, ramp, ramp, ramp, (transparentPixel & 0xFF));
              }
              greyModels[llog] = cm;
            }
          }
          bPixels = new byte[pixSize];
          break;
        case COLOR:
        case COLOR | ALPHA:
        case GRAY | ALPHA:
          cm = ColorModel.getRGBdefault();
          wPixels = new int[pixSize];
          break;
        default:
          throw new PNGException("invalid color type");
      }
      /* this is going to be set in the pixel store
        t.setColorModel(cm);
      t.setHints(interlaceMethod !=0
                 ? ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES
                 : ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
                   ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME);
                   */
      // code added to make it work with ImageDecoder architecture
      setDimensions(width, height);
      setColorModel(cm);
      int flags =
          (interlaceMethod != 0
              ? ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES
              : ImageConsumer.TOPDOWNLEFTRIGHT
                  | ImageConsumer.COMPLETESCANLINES
                  | ImageConsumer.SINGLEPASS
                  | ImageConsumer.SINGLEFRAME);
      setHints(flags);
      headerComplete();
      // end of adding

      int samplesPerPixel =
          ((colorType & PALETTE) != 0
              ? 1
              : ((colorType & COLOR) != 0 ? 3 : 1) + ((colorType & ALPHA) != 0 ? 1 : 0));
      int bitsPerPixel = samplesPerPixel * bitDepth;
      int bytesPerPixel = (bitsPerPixel + 7) >> 3;
      int pass, passLimit;
      if (interlaceMethod == 0) {
        pass = -1;
        passLimit = 0;
      } else {
        pass = 0;
        passLimit = 7;
      }
      // These loops are far from being tuned.  They're this way to make them easy to
      // debug.  Tuning comes later.
      /* code changed. target not needed here
      while(++pass<=passLimit && (t=target)!=null) {
      */
      while (++pass <= passLimit) {
        int row = startingRow[pass];
        int rowInc = rowIncrement[pass];
        int colInc = colIncrement[pass];
        int bWidth = blockWidth[pass];
        int bHeight = blockHeight[pass];
        int sCol = startingCol[pass];
        int rowPixelWidth = (width - sCol + (colInc - 1)) / colInc;
        int rowByteWidth = ((rowPixelWidth * bitsPerPixel) + 7) >> 3;
        if (rowByteWidth == 0) continue;
        int pixelBufferInc = interlaceMethod == 0 ? rowInc * width : 0;
        int rowOffset = rowStride * row;
        boolean firstRow = true;

        byte[] rowByteBuffer = new byte[rowByteWidth];
        byte[] prevRowByteBuffer = new byte[rowByteWidth];
        /* code changed. target not needed here
        while (row < height && (t=target)!=null) {
        */
        while (row < height) {
          int rowFilter = is.read();
          for (int rowFillPos = 0; rowFillPos < rowByteWidth; ) {
            int n = is.read(rowByteBuffer, rowFillPos, rowByteWidth - rowFillPos);
            if (n <= 0) throw new PNGException("missing data");
            rowFillPos += n;
          }
          filterRow(
              rowByteBuffer,
              firstRow ? null : prevRowByteBuffer,
              rowFilter,
              rowByteWidth,
              bytesPerPixel);
          int col = sCol;
          int spos = 0;
          int pixel = 0;
          while (col < width) {
            if (wPixels != null) {
              switch (combinedType) {
                case COLOR | ALPHA | (8 << 3):
                  wPixels[col + rowOffset] =
                      ((rowByteBuffer[spos] & 0xFF) << 16)
                          | ((rowByteBuffer[spos + 1] & 0xFF) << 8)
                          | ((rowByteBuffer[spos + 2] & 0xFF))
                          | ((rowByteBuffer[spos + 3] & 0xFF) << 24);
                  spos += 4;
                  break;
                case COLOR | ALPHA | (16 << 3):
                  wPixels[col + rowOffset] =
                      ((rowByteBuffer[spos] & 0xFF) << 16)
                          | ((rowByteBuffer[spos + 2] & 0xFF) << 8)
                          | ((rowByteBuffer[spos + 4] & 0xFF))
                          | ((rowByteBuffer[spos + 6] & 0xFF) << 24);
                  spos += 8;
                  break;
                case COLOR | (8 << 3):
                  pixel =
                      ((rowByteBuffer[spos] & 0xFF) << 16)
                          | ((rowByteBuffer[spos + 1] & 0xFF) << 8)
                          | ((rowByteBuffer[spos + 2] & 0xFF));
                  if (pixel != transparentPixel) {
                    pixel |= 0xff000000;
                  }
                  wPixels[col + rowOffset] = pixel;
                  spos += 3;
                  break;
                case COLOR | (16 << 3):
                  pixel =
                      ((rowByteBuffer[spos] & 0xFF) << 16)
                          | ((rowByteBuffer[spos + 2] & 0xFF) << 8)
                          | ((rowByteBuffer[spos + 4] & 0xFF));

                  boolean isTransparent = (transparentPixel_16 != null);
                  for (int i = 0; isTransparent && (i < 6); i++) {
                    isTransparent &=
                        (rowByteBuffer[spos + i] & 0xFF) == (transparentPixel_16[i] & 0xFF);
                  }
                  if (!isTransparent) {
                    pixel |= 0xff000000;
                  }
                  wPixels[col + rowOffset] = pixel;
                  spos += 6;
                  break;
                case GRAY | ALPHA | (8 << 3):
                  {
                    int tx = rowByteBuffer[spos] & 0xFF;
                    wPixels[col + rowOffset] =
                        (tx << 16) | (tx << 8) | tx | ((rowByteBuffer[spos + 1] & 0xFF) << 24);
                  }
                  spos += 2;
                  break;
                case GRAY | ALPHA | (16 << 3):
                  {
                    int tx = rowByteBuffer[spos] & 0xFF;
                    wPixels[col + rowOffset] =
                        (tx << 16) | (tx << 8) | tx | ((rowByteBuffer[spos + 2] & 0xFF) << 24);
                  }
                  spos += 4;
                  break;
                default:
                  throw new PNGException("illegal type/depth");
              }
            } else
              switch (bitDepth) {
                case 1:
                  bPixels[col + rowOffset] =
                      (byte) ((rowByteBuffer[spos >> 3] >> (7 - (spos & 7))) & 1);
                  spos++;
                  break;
                case 2:
                  bPixels[col + rowOffset] =
                      (byte) ((rowByteBuffer[spos >> 2] >> ((3 - (spos & 3)) * 2)) & 3);
                  spos++;
                  break;
                case 4:
                  bPixels[col + rowOffset] =
                      (byte) ((rowByteBuffer[spos >> 1] >> ((1 - (spos & 1)) * 4)) & 15);
                  spos++;
                  break;
                case 8:
                  bPixels[col + rowOffset] = rowByteBuffer[spos++];
                  break;
                case 16:
                  bPixels[col + rowOffset] = rowByteBuffer[spos];
                  spos += 2;
                  break;
                default:
                  throw new PNGException("illegal type/depth");
              }
            /*visit (row, col,
            min (bHeight, height - row),
            min (bWidth, width - col)); */
            col += colInc;
          }
          if (interlaceMethod == 0)
            if (wPixels != null) {
              /* code changed. target not needed here
              t.setPixels(0,row,width,1,cm,wPixels,0,width);
              */
              // code added to make it work with ImageDecoder arch
              sendPixels(0, row, width, 1, wPixels, 0, width);
              // end of adding
            } else {
              /* code changed. target not needed here
              t.setPixels(0,row,width,1,cm,bPixels,0,width);
              */
              // code added to make it work with ImageDecoder arch
              sendPixels(0, row, width, 1, bPixels, 0, width);
              // end of adding
            }
          row += rowInc;
          rowOffset += rowInc * rowStride;
          byte[] T = rowByteBuffer;
          rowByteBuffer = prevRowByteBuffer;
          prevRowByteBuffer = T;
          firstRow = false;
        }
        if (interlaceMethod != 0)
          if (wPixels != null) {
            /* code changed. target not needed here
            t.setPixels(0,0,width,height,cm,wPixels,0,width);
            */
            // code added to make it work with ImageDecoder arch
            sendPixels(0, 0, width, height, wPixels, 0, width);
            // end of adding
          } else {
            /* code changed. target not needed here
            t.setPixels(0,0,width,height,cm,bPixels,0,width);
            */
            // code added to make it work with ImageDecoder arch
            sendPixels(0, 0, width, height, bPixels, 0, width);
            // end of adding
          }
      }

      /* Here, the function "visit(row,column,height,width)" obtains the
      next transmitted pixel and paints a rectangle of the specified
      height and width, whose upper-left corner is at the specified row
      and column, using the color indicated by the pixel.  Note that row
      and column are measured from 0,0 at the upper left corner. */

      /* code not needed, don't deal with target
      if((t=target)!=null) {
        if(properties!=null) t.setProperties(properties);
          t.imageComplete(ImageConsumer.STATICIMAGEDONE);
          */

      imageComplete(ImageConsumer.STATICIMAGEDONE, true);

      /* code not needed }
      is.close();
      */
    } catch (IOException e) {
      if (!aborted) {
        /* code not needed
           if((t=target)!=null) {
           PNGEncoder.prChunk(e.toString(),inbuf,pos,limit-pos,true);
        */
        property("error", e);
        /* code not needed
           t.setProperties(properties);
           t.imageComplete(ImageConsumer.IMAGEERROR|ImageConsumer.STATICIMAGEDONE);
        */
        imageComplete(ImageConsumer.IMAGEERROR | ImageConsumer.STATICIMAGEDONE, true);
        throw e;
      }
    } finally {
      try {
        close();
      } catch (Throwable e) {
      }
      /* code not needed
      target = null;
      endTurn();
      */
    }
  }
Ejemplo n.º 2
0
 private void property(String key, float value) {
   property(key, new Float(value));
 }
Ejemplo n.º 3
0
 protected boolean handleChunk(int key, byte[] buf, int st, int len) throws IOException {
   switch (key) {
     case bKGDChunk:
       Color c = null;
       switch (colorType) {
         case COLOR:
         case COLOR | ALPHA:
           pngassert(len == 6);
           c = new Color(buf[st] & 0xff, buf[st + 2] & 0xff, buf[st + 4] & 0xff);
           break;
         case COLOR | PALETTE:
         case COLOR | PALETTE | ALPHA:
           pngassert(len == 1);
           int ix = buf[st] & 0xFF;
           pngassert(red_map != null && ix < red_map.length);
           c = new Color(red_map[ix] & 0xff, green_map[ix] & 0xff, blue_map[ix] & 0xff);
           break;
         case GRAY:
         case GRAY | ALPHA:
           pngassert(len == 2);
           int t = buf[st] & 0xFF;
           c = new Color(t, t, t);
           break;
       }
       if (c != null) property("background", c);
       break;
     case cHRMChunk:
       property(
           "chromaticities",
           new Chromaticities(
               getInt(st),
               getInt(st + 4),
               getInt(st + 8),
               getInt(st + 12),
               getInt(st + 16),
               getInt(st + 20),
               getInt(st + 24),
               getInt(st + 28)));
       break;
     case gAMAChunk:
       if (len != 4) throw new PNGException("bogus gAMA");
       gamma = getInt(st);
       if (gamma != 100000) property("gamma", gamma / 100000.0f);
       break;
     case hISTChunk:
       break;
     case IDATChunk:
       return false;
     case IENDChunk:
       break;
     case IHDRChunk:
       if (len != 13 || (width = getInt(st)) == 0 || (height = getInt(st + 4)) == 0)
         throw new PNGException("bogus IHDR");
       bitDepth = getByte(st + 8);
       colorType = getByte(st + 9);
       compressionMethod = getByte(st + 10);
       filterMethod = getByte(st + 11);
       interlaceMethod = getByte(st + 12);
       /* this is not needed
       if(target!=null) target.setDimensions(width,height);
       */
       break;
     case PLTEChunk:
       {
         int tsize = len / 3;
         red_map = new byte[tsize];
         green_map = new byte[tsize];
         blue_map = new byte[tsize];
         for (int i = 0, j = st; i < tsize; i++, j += 3) {
           red_map[i] = buf[j];
           green_map[i] = buf[j + 1];
           blue_map[i] = buf[j + 2];
         }
       }
       break;
     case pHYsChunk:
       break;
     case sBITChunk:
       break;
     case tEXtChunk:
       int klen = 0;
       while (klen < len && buf[st + klen] != 0) klen++;
       if (klen < len) {
         String tkey = new String(buf, st, klen);
         String tvalue = new String(buf, st + klen + 1, len - klen - 1);
         property(tkey, tvalue);
       }
       break;
     case tIMEChunk:
       property(
           "modtime",
           new GregorianCalendar(
                   getShort(st + 0),
                   getByte(st + 2) - 1,
                   getByte(st + 3),
                   getByte(st + 4),
                   getByte(st + 5),
                   getByte(st + 6))
               .getTime());
       break;
     case tRNSChunk:
       switch (colorType) {
         case PALETTE | COLOR:
         case PALETTE | COLOR | ALPHA:
           int alen = len;
           if (red_map != null) alen = red_map.length;
           alpha_map = new byte[alen];
           System.arraycopy(buf, st, alpha_map, 0, len < alen ? len : alen);
           while (--alen >= len) alpha_map[alen] = (byte) 0xFF;
           break;
         case COLOR: // doesn't deal with 16 bit colors properly
         case COLOR | ALPHA: // doesn't deal with 16 bit colors properly
           pngassert(len == 6);
           if (bitDepth == 16) {
             transparentPixel_16 = new byte[6];
             for (int i = 0; i < 6; i++) {
               transparentPixel_16[i] = (byte) getByte(st + i);
             }
           } else {
             transparentPixel =
                 ((getShort(st + 0) & 0xFF) << 16)
                     | ((getShort(st + 2) & 0xFF) << 8)
                     | ((getShort(st + 4) & 0xFF));
           }
           break;
         case GRAY: // doesn't deal with 16 bit colors properly
         case GRAY | ALPHA: // doesn't deal with 16 bit colors properly
           pngassert(len == 2);
           /* REMIND: Discarding the LSB for 16 bit depth here
            * means that the all pixels which match the MSB
            * will be treated as transparent.
            */
           int t = getShort(st);
           t = 0xFF & ((bitDepth == 16) ? (t >> 8) : t);
           transparentPixel = (t << 16) | (t << 8) | t;
           break;
       }
       break;
     case zTXtChunk:
       break;
   }
   return true;
 }