public void SkipBytes(int bytes) { int blocks = (bytes / BufSize) * BufSize; input.ReadBytes(blocks); for (int i = blocks; i < bytes; i++) GetBits(8); }
/* This will attempt to parse makernotes and return it as an IFD */ //makernote should be self contained Makernote ParseMakerNote(ImageBinaryReader reader, Tag tag, Endianness parentEndian) { //read twice the makernote lenght, should be enough reader.BaseStream.Position = tag.dataOffset + RelativeOffset; byte[] data = reader.ReadBytes((int)Math.Min(tag.dataCount * 3, reader.BaseStream.Length)); return(ParseMakerNote(data, parentEndian, (int)tag.dataOffset)); }
public static void Decode10BitRaw(ImageBinaryReader input, Point2D size, Point2D offset, Image <ushort> rawImage) { int off = (int)(size.width * 10) / 8; var pumps = new byte[size.height][]; //read the data for (int i = 0; i < size.height; i++) { pumps[i] = input.ReadBytes(off); } Parallel.For(0, size.height, i => { long pos = (i + offset.height) * rawImage.fullSize.dim.width + offset.width; var data = pumps[i]; var bytePos = 0; for (uint x = 0; x < size.width;) { rawImage.fullSize.rawView[pos + x++] = (ushort)((data[bytePos++] << 2) + (data[bytePos] >> 6)); rawImage.fullSize.rawView[pos + x++] = (ushort)(((data[bytePos++] & 63) << 4) + (data[bytePos] >> 4)); rawImage.fullSize.rawView[pos + x++] = (ushort)(((data[bytePos++] & 15) << 6) + (data[bytePos] >> 2)); rawImage.fullSize.rawView[pos + x++] = (ushort)(((data[bytePos++] & 3) << 8) + data[bytePos++]); } pumps[i] = null; }); }
internal PanaBitpump(ImageBinaryReader _input, uint load) { var temp = _input.ReadBytes((int)_input.RemainingSize); Array.Resize(ref temp, temp.Length + 32); input = new ImageBinaryReader(temp); vbits = 0; load_flags = (int)load; }
public static void Decode8BitRaw(ImageBinaryReader input, Point2D size, Point2D offset, Image <ushort> rawImage) { var temp = input.ReadBytes((int)size.Area); Parallel.For(0, size.height, y => { var skip = (y + offset.height) * rawImage.fullSize.UncroppedDim.width + offset.width; for (int x = 0; x < size.width; x++) { rawImage.fullSize.rawView[skip + x] = temp[skip + x]; } }); }
public Tag(ImageBinaryReader fileStream, int baseOffset) { parent_offset = baseOffset; TagId = (TagType)fileStream.ReadUInt16(); dataType = (TiffDataType)fileStream.ReadUInt16(); if (TagId == TagType.FUJI_RAW_IFD) { if (dataType == TiffDataType.OFFSET) // FUJI - correct type { dataType = TiffDataType.LONG; } } dataCount = fileStream.ReadUInt32(); dataOffset = 0; if (((dataCount * dataType.GetTypeSize() > 4))) { dataOffset = fileStream.ReadUInt32(); } else { GetData(fileStream); int k = (int)dataCount * dataType.GetTypeSize(); if (k < 4) { fileStream.ReadBytes(4 - k); } } /* if (dataOffset < fileStream.BaseStream.Length && dataOffset > 1) * { * long firstPosition = fileStream.Position; * fileStream.Position = dataOffset + parent_offset; * GetData(fileStream); * fileStream.BaseStream.Position = firstPosition; * ¨*/ }
void DecodeARW2(ImageBinaryReader input, long w, long h, int bpp) { input.Position = 0; if (bpp == 8) { // Since ARW2 compressed images have predictable offsets, we decode them threaded BitPumpPlain bits = new BitPumpPlain(reader); //todo add parralel (parrallel.For not working because onlyone bits so not thread safe; //set one bits pump per row (may be slower) for (uint y = 0; y < rawImage.fullSize.dim.height; y++) { // Realign bits.Offset = (int)(rawImage.fullSize.dim.width * 8 * y) >> 3; uint random = bits.PeekBits(24); // Process 32 pixels (16x2) per loop. for (uint x = 0; x < rawImage.fullSize.dim.width - 30;) { int _max = (int)bits.GetBits(11); int _min = (int)bits.GetBits(11); int _imax = (int)bits.GetBits(4); int _imin = (int)bits.GetBits(4); int sh; for (sh = 0; sh < 4 && 0x80 << sh <= _max - _min; sh++) { ; } for (int i = 0; i < 16; i++) { int p; if (i == _imax) { p = _max; } else if (i == _imin) { p = _min; } else { p = (int)(bits.GetBits(7) << sh) + _min; if (p > 0x7ff) { p = 0x7ff; } } rawImage.SetWithLookUp((ushort)(p << 1), rawImage.fullSize.rawView, (int)((y * rawImage.fullSize.dim.width) + x + i * 2), ref random); } x += (x & 1) != 0 ? (uint)31 : 1; // Skip to next 32 pixels } } } else if (bpp == 12) { byte[] inputTempArray = input.ReadBytes((int)input.BaseStream.Length); if (input.RemainingSize < (w * 3 / 2)) { throw new RawDecoderException("Sony Decoder: Image data section too small, file probably truncated"); } if (input.RemainingSize < (w * h * 3 / 2)) { h = input.RemainingSize / (w * 3 / 2) - 1; } int i = 0; for (uint y = 0; y < h; y++) { for (uint x = 0; x < w; x += 2) { uint g1 = inputTempArray[i++]; uint g2 = inputTempArray[i++]; rawImage.fullSize.rawView[y * rawImage.fullSize.dim.width + x] = (ushort)(g1 | ((g2 & 0xf) << 8)); uint g3 = inputTempArray[i++]; rawImage.fullSize.rawView[y * rawImage.fullSize.dim.width + x + 1] = (ushort)((g2 >> 4) | (g3 << 4)); } } } else { throw new RawDecoderException("Unsupported bit depth"); } }
public void DecodeSlice() { //first read data for each slice for (int i = 0; i < slices.Count; i++) { file.BaseStream.Position = slices[i].byteOffset; slices[i].data = file.ReadBytes((int)slices[i].byteCount); } Parallel.For(0, slices.Count, (i) => { DngSliceElement e = slices[i]; LJPEGPlain l = new LJPEGPlain(e.data, raw, e.mUseBigtable, FixLjpeg) { offX = e.offX, offY = e.offY }; l.StartDecoder(0, e.byteCount); l.input.Dispose(); }); /* Lossy DNG * * // Each slice is a JPEG image * struct jpeg_decompress_struct dinfo; * struct jpeg_error_mgr jerr; * while (!t.slices.empty()) { * DngSliceEleqment e = t.slices.front(); * t.slices.pop(); * byte* complete_buffer = null; * JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW)); * * try { * jpeg_create_decompress(&dinfo); * dinfo.err = jpeg_std_error(&jerr); * jerr.error_exit = my_error_throw; * JPEG_MEMSRC(&dinfo, (unsigned char*)mFile.getData(e.byteOffset, e.byteCount), e.byteCount); * * if (JPEG_HEADER_OK != jpeg_read_header(&dinfo, true)) * ThrowRDE("DngDecoderSlices: Unable to read JPEG header"); * * jpeg_start_decompress(&dinfo); * if (dinfo.output_components != (int) mRaw.getCpp()) * ThrowRDE("DngDecoderSlices: Component count doesn't match"); * int row_stride = dinfo.output_width * dinfo.output_components; * int pic_size = dinfo.output_height * row_stride; * complete_buffer = (byte8*) _aligned_malloc(pic_size, 16); * while (dinfo.output_scanline<dinfo.output_height) { * buffer[0] = (JSAMPROW) (&complete_buffer[dinfo.output_scanline * row_stride]); * if (0 == jpeg_read_scanlines(&dinfo, buffer, 1)) * ThrowRDE("DngDecoderSlices: JPEG Error while decompressing image."); * } * jpeg_finish_decompress(&dinfo); * * // Now the image is decoded, and we copy the image data * int copy_w = Math.Math.Min(((mraw.raw.dim.x - e.offX, dinfo.output_width); * int copy_h = Math.Math.Min(((mraw.raw.dim.y - e.offY, dinfo.output_height); * for (int y = 0; y<copy_h; y++) { * byte[] src = &complete_buffer[row_stride * y]; * UInt16* dst = (UInt16*)mRaw.getData(e.offX, y + e.offY); * for (int x = 0; x<copy_w; x++) { * for (int c=0; c<dinfo.output_components; c++) * dst++ = (* src++); * } * } * } catch (RawDecoderException &err) { * mRaw.setError(err.what()); * } catch (IOException &err) { * mRaw.setError(err.what()); * } * free(buffer); * if (complete_buffer) * _aligned_free(complete_buffer); * jpeg_destroy_decompress(&dinfo); * } * }*/ }
public void Decompress(ImageBinaryReader metadata, uint offset, uint size) { metadata.Position = 0; byte v0 = metadata.ReadByte(); byte v1 = metadata.ReadByte(); int huffSelect = 0; uint split = 0; var pUp1 = new int[2]; var pUp2 = new int[2]; huff[0].UseBigTable = true; if (v0 == 73 || v1 == 88) { metadata.ReadBytes(2110); } if (v0 == 70) { huffSelect = 2; } if (raw.fullSize.ColorDepth == 14) { huffSelect += 3; } pUp1[0] = metadata.ReadInt16(); pUp1[1] = metadata.ReadInt16(); pUp2[0] = metadata.ReadInt16(); pUp2[1] = metadata.ReadInt16(); int max = 1 << raw.fullSize.ColorDepth & 0x7fff; int step = 0, csize = metadata.ReadUInt16(); if (csize > 1) { step = max / (csize - 1); } if (v0 == 68 && v1 == 32 && step > 0) { for (int i = 0; i < csize; i++) { curve[i * step] = metadata.ReadUInt16(); } for (int i = 0; i < max; i++) { curve[i] = (ushort)((curve[i - i % step] * (step - i % step) + curve[i - i % step + step] * (i % step)) / step); } metadata.Position = (562); split = metadata.ReadUInt16(); } else if (v0 != 70 && csize <= 0x4001) { for (int i = 0; i < csize; i++) { curve[i] = metadata.ReadUInt16(); } max = csize; } huff[0].Create(huffSelect); raw.whitePoint = curve[max - 1]; raw.black = curve[0]; raw.table = new TableLookUp(curve, max, true); huff[0].bitPump = new BitPumpMSB(input, offset, size); int pLeft1 = 0, pLeft2 = 0; uint random = huff[0].bitPump.PeekBits(24); for (int y = 0; y < raw.fullSize.dim.height; y++) { if (split != 0 && (y == split)) { huff[0].Create(huffSelect + 1); } pUp1[y & 1] += huff[0].Decode(); pUp2[y & 1] += huff[0].Decode(); pLeft1 = pUp1[y & 1]; pLeft2 = pUp2[y & 1]; long dest = y * raw.fullSize.dim.width; raw.SetWithLookUp((ushort)pLeft1, raw.fullSize.rawView, dest++, ref random); raw.SetWithLookUp((ushort)pLeft2, raw.fullSize.rawView, dest++, ref random); for (int x = 1; x < raw.fullSize.dim.width / 2; x++) { pLeft1 += huff[0].Decode(); pLeft2 += huff[0].Decode(); raw.SetWithLookUp((ushort)pLeft1, raw.fullSize.rawView, dest++, ref random); raw.SetWithLookUp((ushort)pLeft2, raw.fullSize.rawView, dest++, ref random); } } raw.table = null; }
/* This is probably the slowest decoder of them all. * I cannot see any way to effectively speed up the prediction * phase, which is by far the slowest part of this algorithm. * Also there is no way to multithread this code, since prediction * is based on the output of all previous pixel (bar the first four) */ private void DecodeCompressed(ImageBinaryReader s, uint width, uint height) { int nbits; long left0, nw0, left1, nw1; long sign, low, high; long[] acarry0 = new long[3], acarry1 = new long[3]; long pred, diff; //uint pitch = rawImage.pitch; /* Build a table to quickly look up "high" value */ byte[] bittable = new byte[4096]; for (int i = 0; i < 4096; i++) { int b = i; for (high = 0; high < 12; high++) { if (((b >> (11 - (int)high)) & 1) != 0) { break; } } bittable[i] = (byte)Math.Min(12, high); } left0 = nw0 = left1 = nw1 = 0; s.ReadBytes(7); BitPumpMSB bits = new BitPumpMSB(s); for (int y = 0; y < height; y++) { var pos = y * rawImage.fullSize.UncroppedDim.width; acarry0 = new long[3]; acarry1 = new long[3]; bool y_border = y < 2; bool border = true; for (int x = 0; x < width; x++) { bits.Fill(); int i = 0; if (acarry0[2] < 3) { i = 2; } for (nbits = 2 + i; acarry0[0] >> (nbits + i) != 0; nbits++) { ; } uint b = bits.PeekBits(15); sign = (b >> 14) * -1; low = (b >> 12) & 3; high = bittable[b & 4095]; // Skip bytes used above or read bits if (high == 12) { bits.SkipBits(15); high = bits.GetBits(16 - nbits) >> 1; } else { bits.SkipBits((int)high + 1 + 3); } acarry0[0] = (high << nbits) | bits.GetBits(nbits); diff = (acarry0[0] ^ sign) + acarry0[1]; acarry0[1] = (diff * 3 + acarry0[1]) >> 5; acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1; if (border) { if (y_border && x < 2) { pred = 0; } else if (y_border) { pred = left0; } else { pred = nw0 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; } rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low)); // Set predictor left0 = rawImage.fullSize.rawView[pos + x]; } else { // Have local variables for values used several tiles // (having a "UInt16 *dst_up" that caches dest[-pitch+((int)x)] is actually slower, probably stack spill or aliasing) int up = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; long leftMinusNw = left0 - nw0; long upMinusNw = up - nw0; // Check if sign is different, and one is not zero if (leftMinusNw * upMinusNw < 0) { if (Other_abs(leftMinusNw) > 32 || Other_abs(upMinusNw) > 32) { pred = left0 + upMinusNw; } else { pred = (left0 + up) >> 1; } } else { pred = Other_abs(leftMinusNw) > Other_abs(upMinusNw) ? left0 : up; } rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low)); // Set predictors left0 = rawImage.fullSize.rawView[pos + x]; nw0 = up; } // ODD PIXELS x += 1; bits.Fill(); i = 0; if (acarry1[2] < 3) { i = 2; } for (nbits = 2 + i; acarry1[0] >> (nbits + i) != 0; nbits++) { ; } b = bits.PeekBits(15); sign = (b >> 14) * -1; low = (b >> 12) & 3; high = bittable[b & 4095]; // Skip bytes used above or read bits if (high == 12) { bits.SkipBits(15); high = bits.GetBits(16 - nbits) >> 1; } else { bits.SkipBits((int)high + 1 + 3); } acarry1[0] = (high << nbits) | bits.GetBits(nbits); diff = (acarry1[0] ^ sign) + acarry1[1]; acarry1[1] = (diff * 3 + acarry1[1]) >> 5; acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1; if (border) { if (y_border && x < 2) { pred = 0; } else if (y_border) { pred = left1; } else { pred = nw1 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; } rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low)); } else { int up = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; long leftminusNw = left1 - nw1; long upminusNw = up - nw1; // Check if sign is different, and one is not zero if (leftminusNw * upminusNw < 0) { if (Other_abs(leftminusNw) > 32 || Other_abs(upminusNw) > 32) { pred = left1 + upminusNw; } else { pred = (left1 + up) >> 1; } } else { pred = Other_abs(leftminusNw) > Other_abs(upminusNw) ? left1 : up; } rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low)); nw1 = up; } border = y_border; } } }
public void ParseSOS() { if (!frame.Initialized) { throw new RawDecoderException("Frame not yet initialized (SOF Marker not parsed)"); } input.ReadInt16(); uint soscps = input.ReadByte(); if (frame.numComponents != soscps) { throw new RawDecoderException("Component number mismatch."); } for (int i = 0; i < frame.numComponents; i++) { uint cs = input.ReadByte(); uint count = 0; // Find the correct component while (frame.ComponentInfo[count].componentId != cs) { if (count >= frame.numComponents) { throw new RawDecoderException("Invalid Component Selector"); } count++; } uint b1 = input.ReadByte(); uint td = b1 >> 4; if (td > 3) { throw new RawDecoderException("Invalid Huffman table selection"); } if (!huff[td].Initialized) { throw new RawDecoderException("Invalid Huffman table selection, not defined."); } if (count > 3) { throw new RawDecoderException("Component count out of range"); } frame.ComponentInfo[count].dcTblNo = td; } predictor = input.ReadByte(); if (predictor > 7) { throw new RawDecoderException("Invalid predictor mode."); } input.ReadBytes(1); // Se + Ah Not used in LJPEG int b = input.ReadByte(); Pt = b & 0xf; // Point Transform bits = new BitPumpJPEG(input); for (int i = 0; i < huff.Length; i++) { huff[i].bitPump = bits; huff[i].precision = frame.precision; } DecodeScan(); input.Position = bits.Offset; }