private async Task ApplyTiff() { System.Diagnostics.Debug.WriteLine("Begin Apply Tiff"); int i, max_samp = 0, raw = -1, thm = -1; JHead jh = new JHead(); thumb_misc = 16; if (thumb_offset > 0) { ifp.Seek(thumb_offset, SeekOrigin.Begin); if (await LJpegStartAsync(jh, 1) > 0) { thumb_misc = jh.bits; thumb_width = jh.wide; thumb_height = jh.high; } } for (i = (int)tiff_nifds - 1; i >= 0; i--) { if (tiff_ifd_c[i].shutter != 0) shutter = tiff_ifd_c[i].shutter; tiff_ifd_c[i].shutter = shutter; } for (i = 0; i < tiff_nifds; i++) { if (max_samp < tiff_ifd_c[i].samples) max_samp = tiff_ifd_c[i].samples; if (max_samp > 3) max_samp = 3; if ((tiff_ifd_c[i].comp != 6 || tiff_ifd_c[i].samples != 3) && (tiff_ifd_c[i].width | tiff_ifd_c[i].height) < 0x10000 && tiff_ifd_c[i].width * tiff_ifd_c[i].height > raw_width * raw_height) { raw_width = (ushort)tiff_ifd_c[i].width; raw_height = (ushort)tiff_ifd_c[i].height; tiff_bps = (uint)tiff_ifd_c[i].bps; tiff_compress = (uint)tiff_ifd_c[i].comp; data_offset = (uint)tiff_ifd_c[i].offset; tiff_flip = (uint)tiff_ifd_c[i].flip; tiff_samples = (uint)tiff_ifd_c[i].samples; tile_width = (uint)tiff_ifd_c[i].tile_width; tile_length = (uint)tiff_ifd_c[i].tile_length; raw = i; } } for (i = (int)tiff_nifds - 1; i >= 0; i--) { if (tiff_ifd_c[i].flip != 0) tiff_flip = (uint)tiff_ifd_c[i].flip; } for (i = 0; i < tiff_nifds; i++) { if (i != raw && tiff_ifd_c[i].samples == max_samp && tiff_ifd_c[i].width * tiff_ifd_c[i].height / ((tiff_ifd_c[i].bps * tiff_ifd_c[i].bps) + 1) > thumb_width * thumb_height / ((thumb_misc * thumb_misc) + 1) && tiff_ifd_c[i].comp != 34892) { thumb_width = tiff_ifd_c[i].width; thumb_height = tiff_ifd_c[i].height; thumb_offset = (uint)tiff_ifd_c[i].offset; thumb_length = (uint)tiff_ifd_c[i].bytes; thumb_misc = tiff_ifd_c[i].bps; thm = i; } } if (thm >= 0) { thumb_misc |= tiff_ifd_c[thm].samples << 5; switch (tiff_ifd_c[thm].comp) { case 0: write_thumb = WriteLayerThumb; break; case 1: if (tiff_ifd_c[thm].bps <= 8) write_thumb = WritePpmThumb; else if (make.strcmp("Imacon")) write_thumb = WritePpm16Thumb; else write_thumb = null; break; case 65000: write_thumb = null; break; } } }
private async Task<int> LJpegStartAsync(JHead jh, int info_only) { System.Diagnostics.Debug.WriteLine("Begin LJpeg Start"); ushort c = 0, tag, len; byte[] data = new byte[0x10000]; jh.restart = Int32.MaxValue; ifp.ReadByte(); if (ifp.ReadByte() != 0xd8) return 0; do { if (ifp.Read(data, 0, 4) == 0) return 0; tag = (ushort)(data[0] << 8 | data[1]); len = (ushort)((data[2] << 8 | data[3]) - 2); if (tag <= 0xff00) return 0; await ifp.ReadAsync(data, 0, len); switch (tag) { case 0xffc3: jh.sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; jh.algo = tag & 0xff; jh.bits = data[0]; jh.high = data[1] << 8 | data[2]; jh.wide = data[3] << 8 | data[4]; jh.clrs = data[5] + jh.sraw; if (len == 9 && dng_version > 0) ifp.ReadByte(); break; case 0xffc1: case 0xffc0: jh.algo = tag & 0xff; jh.bits = data[0]; jh.high = data[1] << 8 | data[2]; jh.wide = data[3] << 8 | data[4]; jh.clrs = data[5] + jh.sraw; if (len == 9 && dng_version > 0) ifp.ReadByte(); break; case 0xffda: jh.psv = data[1 + data[0] * 2]; jh.bits -= data[3 + data[0] * 2] & 15; break; case 0xffdb: jh.quant[c] = (ushort)(data[c * 2 + 1] << 8 | data[c * 2 + 2]); break; case 0xffdd: jh.restart = data[0] << 8 | data[1]; break; } } while (tag != 0xffda); // Info only support implemented for now return 1; }
private async Task<int> ParseTiffIfdAsync(int base_c) { System.Diagnostics.Debug.WriteLine("Begin Parse Tiff Ifd"); tiff_ifd_c.Add(new TiffIfd()); UInt32 entries = 0, tag = 0, type = 0, len = 0, save = 0; int ifd, i = 0; JHead jh = new JHead(); byte[] software = new byte[64]; ifd = (int)tiff_nifds++; entries = await Get2Async(); if (entries > 512) return 1; while (entries-- > 0) { var result = await TiffGet((UInt32)base_c); tag = result.Tag; type = result.Type; len = result.Len; save = result.Save; switch (tag) { case 5: width = await Get2Async(); break; case 6: height = await Get2Async(); break; case 7: width += await Get2Async(); break; case 9: filters = await Get2Async(); break; case 23: if (type == 3) iso_speed = (float)await Get2Async(); break; case 46: if (type != 7 || ifp.ReadByte() != 0xff || ifp.ReadByte() != 0xd8) break; thumb_offset = (uint)(ifp.Position - 2); thumb_length = len; break; case 61440: /* Fuji HS10 table */ ifp.Seek(await Get4Async() + base_c, SeekOrigin.Begin); await ParseTiffIfdAsync(base_c); break; case 2: case 256: case 61441: tiff_ifd_c[ifd].width = (int)await GetIntAsync((int)type); break; case 3: case 257: case 61442: tiff_ifd_c[ifd].height = (int)await GetIntAsync((int)type); break; case 258: /* BitsPerSample */ case 61443: tiff_ifd_c[ifd].samples = (int)(len & 7); tiff_ifd_c[ifd].bps = (int)await GetIntAsync((int)type); break; case 61446: raw_height = 0; if (tiff_ifd_c[ifd].bps > 12) break; load_flags = (uint)(await Get4Async() > 0 ? 24 : 80); break; case 259: /* Compression */ tiff_ifd_c[ifd].comp = (int)await GetIntAsync((int)type); break; case 262: /* PhotometricInterpretation */ tiff_ifd_c[ifd].phint = await Get2Async(); break; case 270: /* ImageDescription */ await ifp.ReadAsync(desc, 0, 512); break; case 271: await ifp.ReadAsync(make, 0, 64); break; case 272: await ifp.ReadAsync(model, 0, 64); break; case 280: /* Panasonic RW2 offset */ if (type != 4) break; load_flags = 0x2008; goto case 61447; case 273: case 513: case 61447: tiff_ifd_c[ifd].offset = (int)(await Get4Async() + base_c); if (tiff_ifd_c[ifd].bps == 0 && tiff_ifd_c[ifd].offset > 0) { ifp.Seek(tiff_ifd_c[ifd].offset, SeekOrigin.Begin); if (await LJpegStartAsync(jh, 1) > 0) { tiff_ifd_c[ifd].comp = 6; tiff_ifd_c[ifd].width = jh.wide; tiff_ifd_c[ifd].height = jh.high; tiff_ifd_c[ifd].bps = jh.bits; tiff_ifd_c[ifd].samples = jh.clrs; if (!(jh.sraw > 0 || (jh.clrs & 1) > 0)) tiff_ifd_c[ifd].width *= jh.clrs; if ((tiff_ifd_c[ifd].width > 4 * tiff_ifd_c[ifd].height) && jh.clrs > 0) { tiff_ifd_c[ifd].width /= 2; tiff_ifd_c[ifd].height *= 2; } i = order; await ParseTiffAsync(tiff_ifd_c[ifd].offset + 12); order = (short)i; } } break; case 274: tiff_ifd_c[ifd].flip = "50132467"[await Get2Async() & 7] - '0'; break; case 277: /* SamplesPerPixel */ tiff_ifd_c[ifd].samples = (int)await GetIntAsync((int)type) & 7; break; case 279: case 514: case 61448: tiff_ifd_c[ifd].bytes = (int)await Get4Async(); break; case 305: case 11: await ifp.ReadAsync(software, 0, 64); break; case 306: /* DateTime */ GetTimestamp(0); break; case 315: /* artist */ await ifp.ReadAsync(artist, 0, 64); break; case 322: /* TileWidth */ tiff_ifd_c[ifd].tile_width = (int)await GetIntAsync((int)type); break; case 323: /* TileLength */ tiff_ifd_c[ifd].tile_length = (int)await GetIntAsync((int)type); break; case 324: /* TileOffsets */ tiff_ifd_c[ifd].offset = (int)(len > 1 ? ifp.Position : await Get4Async()); if (len == 1) tiff_ifd_c[ifd].tile_width = tiff_ifd_c[ifd].tile_length = 0; if (len == 4) { is_raw = 5; } break; case 330: /* SubIFDs */ if (!model.strcmp("DSLR-A100") && tiff_ifd_c[ifd].width == 3872) { data_offset = (uint)(await Get4Async() + base_c); ifd++; break; } while (len-- > 0) { i = (int)ifp.Position; ifp.Seek(await Get4Async() + base_c, SeekOrigin.Begin); if (await ParseTiffIfdAsync(base_c) > 0) break; ifp.Seek(i + 4, SeekOrigin.Begin); } break; case 33434: tiff_ifd_c[ifd].shutter = shutter = (float)await GetRealAsync((int)type); break; case 33437: aperture = (float)await GetRealAsync((int)type); break; case 34303: make.strncpy("Leaf".ToByteArray(), 4); break; case 34310: /* Leaf metadata */ await ParseMos((int)ifp.Position); make.strncpy("Leaf".ToByteArray(), 4); break; case 34665: ifp.Seek(await Get4Async() + base_c, SeekOrigin.Begin); await ParseExif(base_c); break; case 37386: focal_len = (float)await GetRealAsync((int)type); break; case 37393: shot_order = await GetIntAsync((int)type); break; case 51009: /* OpcodeList2 */ meta_offset = (uint)ifp.Position; break; } ifp.Seek(save, SeekOrigin.Begin); } return 0; }