@Override public void write(byte[] buffer,int offset,int length) throws IOException {
  while ((mByteToSkip > 0 || mByteToCopy > 0 || mState != STATE_JPEG_DATA) && length > 0) {
    if (mByteToSkip > 0) {
      int byteToProcess=length > mByteToSkip ? mByteToSkip : length;
      length-=byteToProcess;
      mByteToSkip-=byteToProcess;
      offset+=byteToProcess;
    }
    if (mByteToCopy > 0) {
      int byteToProcess=length > mByteToCopy ? mByteToCopy : length;
      out.write(buffer,offset,byteToProcess);
      length-=byteToProcess;
      mByteToCopy-=byteToProcess;
      offset+=byteToProcess;
    }
    if (length == 0) {
      return;
    }
switch (mState) {
case STATE_SOI:
      int byteRead=requestByteToBuffer(2,buffer,offset,length);
    offset+=byteRead;
  length-=byteRead;
if (mBuffer.position() < 2) {
  return;
}
mBuffer.rewind();
if (mBuffer.getShort() != JpegHeader.SOI) {
throw new IOException("Not a valid jpeg image, cannot write exif");
}
out.write(mBuffer.array(),0,2);
mState=STATE_FRAME_HEADER;
mBuffer.rewind();
writeExifData();
break;
case STATE_FRAME_HEADER:
byteRead=requestByteToBuffer(4,buffer,offset,length);
offset+=byteRead;
length-=byteRead;
if (mBuffer.position() == 2) {
short tag=mBuffer.getShort();
if (tag == JpegHeader.EOI) {
out.write(mBuffer.array(),0,2);
mBuffer.rewind();
}
}
if (mBuffer.position() < 4) {
return;
}
mBuffer.rewind();
short marker=mBuffer.getShort();
if (marker == JpegHeader.APP1) {
mByteToSkip=(mBuffer.getShort() & 0x0000ffff) - 2;
mState=STATE_JPEG_DATA;
}
 else if (!JpegHeader.isSofMarker(marker)) {
out.write(mBuffer.array(),0,4);
mByteToCopy=(mBuffer.getShort() & 0x0000ffff) - 2;
}
 else {
out.write(mBuffer.array(),0,4);
mState=STATE_JPEG_DATA;
}
mBuffer.rewind();
}
}
if (length > 0) {
out.write(buffer,offset,length);
}
}

@ Override public void write ( byte [ ] buffer , int offset , int length ) throws IOException { while ( ( mByteToSkip > 0 || mByteToCopy > 0 || mState != STATE_JPEG_DATA ) && length > 0 ) { if ( mByteToSkip > 0 ) { int byteToProcess = length > mByteToSkip ? mByteToSkip : length ; length -= byteToProcess ; mByteToSkip -= byteToProcess ; offset += byteToProcess ; } if ( mByteToCopy > 0 ) { int byteToProcess = length > mByteToCopy ? mByteToCopy : length ; out . write ( buffer , offset , byteToProcess ) ; length -= byteToProcess ; mByteToCopy -= byteToProcess ; offset += byteToProcess ; } if ( length == 0 ) { return ; } switch ( mState ) { case STATE_SOI : int byteRead = requestByteToBuffer ( 2 , buffer , offset , length ) ; offset += byteRead ; length -= byteRead ; if ( mBuffer . position ( ) < 2 ) { return ; } mBuffer . rewind ( ) ; if ( mBuffer . getShort ( ) != JpegHeader . SOI ) { throw new IOException ( "Not a valid jpeg image, cannot write exif" ) ; } out . write ( mBuffer . array ( ) , 0 , 2 ) ; mState = STATE_FRAME_HEADER ; mBuffer . rewind ( ) ; writeExifData ( ) ; break ; case STATE_FRAME_HEADER : byteRead = requestByteToBuffer ( 4 , buffer , offset , length ) ; offset += byteRead ; length -= byteRead ; if ( mBuffer . position ( ) == 2 ) { short tag = mBuffer . getShort ( ) ; if ( tag == JpegHeader . EOI ) { out . write ( mBuffer . array ( ) , 0 , 2 ) ; mBuffer . rewind ( ) ; } } if ( mBuffer . position ( ) < 4 ) { return ; } mBuffer . rewind ( ) ; short marker = mBuffer . getShort ( ) ; if ( marker == JpegHeader . APP1 ) { mByteToSkip = ( mBuffer . getShort ( ) & 0x0000ffff ) - 2 ; mState = STATE_JPEG_DATA ; } else if ( ! JpegHeader . isSofMarker ( marker ) ) { out . write ( mBuffer . array ( ) , 0 , 4 ) ; mByteToCopy = ( mBuffer . getShort ( ) & 0x0000ffff ) - 2 ; } else { out . write ( mBuffer . array ( ) , 0 , 4 ) ; mState = STATE_JPEG_DATA ; } mBuffer . rewind ( ) ; } } if ( length > 0 ) { out . write ( buffer , offset , length ) ; } }
writes the image out . the input data should be a valid jpeg format . after writing , it ' s exif header will be replaced by the given header .
