private Picture decodeScan(MemoryStream data, FrameHeader header, ScanHeader scan, VLC[] huffTables, int[][] quant, int[][] data2, int field, int step) { int blockW = header.getHmax(); int blockH = header.getVmax(); int mcuW = blockW << 3; int mcuH = blockH << 3; int width = header.width; int height = header.height; int xBlocks = (width + mcuW - 1) >> (blockW + 2); int yBlocks = (height + mcuH - 1) >> (blockH + 2); int nn = blockW + blockH; Picture result = new Picture(xBlocks << (blockW + 2), yBlocks << (blockH + 2), data2, nn == 4 ? ColorSpace.YUV420J : (nn == 3 ? ColorSpace.YUV422J : ColorSpace.YUV444J), new Rect(0, 0, width, height)); BitReader bits = new BitReader(data); int[] dcPredictor = new int[] { 1024, 1024, 1024 }; for (int by = 0; by < yBlocks; by++) { for (int bx = 0; bx < xBlocks && bits.moreData(); bx++) { decodeMCU(bits, dcPredictor, quant, huffTables, result, bx, by, blockW, blockH, field, step); } } return(result); }
public static ScanHeader read(MemoryStream bb) { ScanHeader scan = new ScanHeader(); scan.ls = bb.getShort() & 0xffff; scan.ns = bb.get() & 0xff; scan.components = new Component[scan.ns]; for (int i = 0; i < scan.components.Length; i++) { Component c = scan.components[i] = new Component(); c.cs = bb.get() & 0xff; int tdta = bb.get() & 0xff; c.td = (tdta & 0xf0) >> 4; c.ta = (tdta & 0x0f); } scan.ss = bb.get() & 0xff; scan.se = bb.get() & 0xff; int ahal = bb.get() & 0xff; scan.ah = (ahal & 0xf0) >> 4; scan.al = (ahal & 0x0f); return(scan); }
public Picture decodeField(MemoryStream data, int[][] data2, int field, int step) { Picture result = null; FrameHeader header = null; VLC[] huffTables = new VLC[] { JpegConst.YDC_DEFAULT, JpegConst.CDC_DEFAULT, JpegConst.YAC_DEFAULT, JpegConst.CAC_DEFAULT }; int[][] quant = new int[4][]; ScanHeader scan = null; while (data.hasRemaining()) { int marker = data.get() & 0xff; if (marker == 0) { continue; } if (marker != 0xFF) { throw new Exception("@" + data.Position + " Marker expected: 0x" + marker.ToString("X")); } int b; while ((b = data.get() & 0xff) == 0xff) { ; } // Debug.trace("%s", JpegConst.toString(b)); if (b == JpegConst.SOF0) { header = FrameHeader.read(data); // Debug.trace(" %s", image.frame); } else if (b == JpegConst.DHT) { int len1 = data.getShort() & 0xffff; MemoryStream buf = StreamExtensions.read(data, len1 - 2); while (buf.hasRemaining()) { int tableNo = buf.get() & 0xff; huffTables[(tableNo & 1) | ((tableNo >> 3) & 2)] = readHuffmanTable(buf); } } else if (b == JpegConst.DQT) { int len4 = data.getShort() & 0xffff; MemoryStream buf = StreamExtensions.read(data, len4 - 2); while (buf.hasRemaining()) { int ind = buf.get() & 0xff; quant[ind] = readQuantTable(buf); } } else if (b == JpegConst.SOS) { if (scan != null) { throw new Exception("unhandled - more than one scan header"); } scan = ScanHeader.read(data); // Debug.trace(" %s", image.scan); result = decodeScan(readToMarker(data), header, scan, huffTables, quant, data2, field, step); } else if (b == JpegConst.SOI || (b >= JpegConst.RST0 && b <= JpegConst.RST7)) { // Nothing } else if (b == JpegConst.EOI) { break; } else if (b >= JpegConst.APP0 && b <= JpegConst.COM) { int len3 = data.getShort() & 0xffff; StreamExtensions.read(data, len3 - 2); } else if (b == JpegConst.DRI) { int lr = data.getShort() & 0xffff; int ri = data.getShort() & 0xffff; // Debug.trace("DRI Lr: %d Ri: %d", lr, ri); //Asserts.assertEquals(0, ri); } else { throw new Exception("unhandled marker " + JpegConst.toString(b)); } } return(result); }