package mjpeg; import java.io.*; //Random access file writer import java.util.*; //Vector import com.keypoint.*; //pngCodec import java.awt.image.BufferedImage; import java.awt.Dimension; public class MpngWriter{ long frameNo = 0; Vector<Long> frames; Vector<Integer> fsizes; long movi; long[] frameP =null; //Frame pointer long[] position = null; //File position pointer RandomAccessFile videoFile =null; //Video file to write to int height; int width; long frameCount; //Constructor public MpngWriter(String fileName,Dimension size) throws Exception{ this.width = size.width; this.height = size.height; frameP = new long[3]; position = new long[3]; frames = new Vector<Long>(); fsizes = new Vector<Integer>(); frameCount = 0; videoFile = new RandomAccessFile(fileName,"rw"); } public MpngWriter(String fileName,int width,int height) throws Exception{ this.width = width; this.height = height; frameP = new long[3]; position = new long[3]; frames = new Vector<Long>(); fsizes = new Vector<Integer>(); frameCount = 0; videoFile = new RandomAccessFile(fileName,"rw"); } public void writeHeader() throws Exception{ String text = "RIFF"; videoFile.write(text.getBytes("ISO-8859-1")); //Riff videoFile.write(intToByteArray(0)); //File size in bytes-8 //AVI text = "AVI "; videoFile.write(text.getBytes("ISO-8859-1")); //AVI text = "LIST"; videoFile.write(text.getBytes("ISO-8859-1")); //LIST videoFile.write(intToByteArray(192)); //list size (header size-12) text = "hdrl"; videoFile.write(text.getBytes("ISO-8859-1")); //main header text = "avih"; videoFile.write(text.getBytes("ISO-8859-1")); //avi header videoFile.write(intToByteArray(14*4)); //avih size in bytes //AVI header data videoFile.write(intToByteArray(40000)); //usec per frame videoFile.write(intToByteArray(25*3*width*height)); //bytes per sec videoFile.write(intToByteArray(0)); //reserved videoFile.write(intToByteArray(2320)); //flags (none required for raw) frameP[0] = videoFile.getFilePointer(); videoFile.write(intToByteArray(0)); //total frames (none required for raw) videoFile.write(intToByteArray(0)); //initial frames (0 for non-interleaved) videoFile.write(intToByteArray(1)); //No. of streams videoFile.write(intToByteArray(width*height*3)); //Buffer size videoFile.write(intToByteArray(width)); //Width videoFile.write(intToByteArray(height)); //Height videoFile.write(intToByteArray(0)); //Reserved[4] set to zero videoFile.write(intToByteArray(0)); //Reserved[4] set to zero videoFile.write(intToByteArray(0)); //Reserved[4] set to zero videoFile.write(intToByteArray(0)); //Reserved[4] set to zero //AVI header written //Stream header text = "LIST"; videoFile.write(text.getBytes("ISO-8859-1")); videoFile.write(intToByteArray(116)); //list size in bytes text = "strl"; //Stream list videoFile.write(text.getBytes("ISO-8859-1")); //Stream list text = "strh"; //Stream header videoFile.write(text.getBytes("ISO-8859-1")); //videoFileStream header videoFile.write(intToByteArray(56)); //videoFileStream header size in bytes //Stream header data text = "vids"; //Stream header videoFile.write(text.getBytes("ISO-8859-1")); //videoFileStream header text = "MPNG"; //Stream handler videoFile.write(text.getBytes("ISO-8859-1")); //Stream handler videoFile.write(intToByteArray(0)); //Flags videoFile.write(intToByteArray(0)); //Priority none needed for raw.. videoFile.write(intToByteArray(0)); //Language needed for raw.. //InitialFrames not used -> no audio... videoFile.write(intToByteArray(1)); //dwScale videoFile.write(intToByteArray(25)); //dwRate videoFile.write(intToByteArray(0)); //dwStart frameP[1] = videoFile.getFilePointer(); videoFile.write(intToByteArray(0)); //dwLength videoFile.write(intToByteArray(0)); //dwBuffer videoFile.write(intToByteArray(-1)); //dwQuality videoFile.write(intToByteArray(0)); //dwSampleSize videoFile.write(intToByteArray(0)); //rcFrame videoFile.write(intToByteArray(0)); //rcFrame //Stream header data written text = "strf"; //Stream format videoFile.write(text.getBytes("ISO-8859-1")); //videoFileStream format videoFile.write(intToByteArray(40)); //videoFileStream fomat size in bytes videoFile.write(intToByteArray(40)); //Format header length = 40 //format data videoFile.write(intToByteArray(width)); //width videoFile.write(intToByteArray(height)); //height videoFile.write(shortToByteArray((short) 1)); //planes = must be 1 videoFile.write(shortToByteArray((short) 0)); //bitCount (0 =jpeg tai png) text = "MPNG"; //Compression videoFile.write(text.getBytes("ISO-8859-1")); //compression videoFile.write(intToByteArray(width*height*3)); //image size in bytes videoFile.write(intToByteArray(0)); //xpixels per meter videoFile.write(intToByteArray(0)); //ypixels per meter videoFile.write(intToByteArray(0)); //ClrUsed videoFile.write(intToByteArray(0)); //ClrImportant //format data written... //DATA chunk!! text = "LIST"; //MOVI chunk videoFile.write(text.getBytes("ISO-8859-1")); //Movi chunk frameP[2] = videoFile.getFilePointer(); //Insert pointer for decoded data videoFile.write(intToByteArray(0)); //Decoded Data size!! movi = videoFile.getFilePointer(); text = "movi"; //MOVI list name videoFile.write(text.getBytes("ISO-8859-1")); //Movi list name } //Functions public void write_frame(BufferedImage image) throws Exception{ String text = "00dc"; //MOVI chunk position[0] =videoFile.getFilePointer(); videoFile.write(text.getBytes("ISO-8859-1")); //Movi chunk videoFile.write(intToByteArray(width*height*3));//Movi chunk size place holder.... position[1] =videoFile.getFilePointer(); write_PNG(image); if ((videoFile.getFilePointer()-position[0])%4 > 0){ //Zero padding byte[] padding = new byte[(int) ((videoFile.getFilePointer()-position[0])%4)]; videoFile.write(padding); } position[2] =videoFile.getFilePointer(); videoFile.seek(position[0]+4); videoFile.write(intToByteArray((int) (position[2]-position[1]))); //Movi chunk size videoFile.seek(position[2]); frames.add(position[0]-movi); fsizes.add((int) (position[2]-position[1])); ++frameCount; } public void finalize_mjpeg() throws Exception{ long currentPosition = videoFile.getFilePointer(); long idxPos = currentPosition; videoFile.seek(movi-4); videoFile.write(intToByteArray((int) (currentPosition-movi))); //Movi chunk size videoFile.seek(currentPosition); //Write index String text = "idx1"; //idx1 chunk videoFile.write(text.getBytes("ISO-8859-1")); //idx1 chunk videoFile.write(intToByteArray((int) (frameCount*4*4))); //index size for (int k = 0;k<frameCount;k++){ text = "00dc"; //idx1 chunk videoFile.write(text.getBytes("ISO-8859-1")); //idx1 chunk videoFile.write(intToByteArray((int) 16)); //Key frame flag!! videoFile.write(intToByteArray(frames.get(k).intValue())); //offset from BEGINNING of (thus the +4) movi!! videoFile.write(intToByteArray((int) (fsizes.get(k)))); //chunk size } currentPosition = videoFile.getFilePointer(); videoFile.seek(4); videoFile.write(intToByteArray((int) (currentPosition-8))); //File size videoFile.seek(frameP[0]); videoFile.write(intToByteArray((int) frameCount)); videoFile.seek(frameP[1]); videoFile.write(intToByteArray((int) frameCount)); //frames2 videoFile.seek(frameP[2]); videoFile.write(intToByteArray((int) (idxPos-movi))); //encoded image data amount //Index written... //Close videoFile videoFile.close(); } void write_PNG(BufferedImage data) throws Exception { PngEncoderB encoder = new PngEncoderB(data); byte[] compressedData = encoder.pngEncode(); videoFile.write(compressedData); } byte[] intToByteArray(int value){ // return new byte[] {(byte) (value >> 24 & 0xFF),(byte) (value >> 16 & 0xFF),(byte) (value >> 8 & 0xFF),(byte) (value & 0xFF)}; return new byte[] {(byte) (value & 0xFF),(byte) ((value >> 8) & 0xFF),(byte) ((value >> 16) & 0xFF),(byte) ((value >> 24) & 0xFF)}; } byte[] shortToByteArray(short value){ // return new byte[] {(byte) (value >> 8 & 0xFF),(byte) (value & 0xFF)}; return new byte[] {(byte) (value & 0xFF),(byte) ((value>>8) & 0xFF)}; } byte[] intArrayToByteArray(int[] arrayIn){ byte[] arrayOut = new byte[arrayIn.length*4]; byte[] temp; for (int i= 0; i<arrayIn.length; ++i){ temp = intToByteArray(arrayIn[i]); for (int j = 0; j< 4; ++j){ arrayOut[4*i+j] = temp[j]; } } return arrayOut; } public static void main(String[] args) { int videon_korkeus =500; int videon_leveys = 500; //MJPEG valmistelu MpngWriter writer = null; try{ writer = new MpngWriter("H:/UserData/winMigrationBU/Deakin/JGREYADJUST/figs/testi.avi",videon_leveys,videon_korkeus); writer.writeHeader(); }catch (Exception err){System.out.println("couldn't open writer");} //TALLENNETAAN VIDEOKSI... //printf("Kuvaa tayttamaan\n"); int[] data = new int[videon_leveys*videon_korkeus]; for (int jjj = 0;jjj<videon_korkeus;++jjj){ for (int iii = 0;iii<videon_leveys;++iii){ data[iii+jjj*videon_leveys]= ((0xff & (byte) iii)<<8*2) | (0xff & (byte) jjj); //R } } BufferedImage buffImg = new BufferedImage(videon_leveys, videon_korkeus, BufferedImage.TYPE_INT_BGR); for (int j = 0; j<videon_korkeus;++j){ for (int i = 0; i<videon_leveys;++i){ buffImg.setRGB(i,j,data[i+j*videon_leveys]); } } //Kuva valmis for (int i = 0;i<100;++i){ try{ writer.write_frame(buffImg); //add frame }catch (Exception err){System.out.println("couldn't write frame");} System.out.println("Kuva "+i); } //Done try{ writer.finalize_mjpeg(); }catch (Exception err){System.out.println("couldn't finalize");} System.out.println("Valmista tuli\n"); } }