コード例 #1
0
ファイル: Channel.cpp プロジェクト: TannerTaphorn/datastore
void Channel::move_root_upwards(TileIndex new_root_index, TileIndex old_root_index) {
  Tile old_root_tile;
  Tile empty_tile;
  assert(read_tile(old_root_index, old_root_tile));
  TileIndex ti = old_root_index;
  while (ti != new_root_index) {
    write_tile(ti.sibling(), empty_tile);
    write_tile(ti.parent(), old_root_tile);
    ti = ti.parent();
  }
}
コード例 #2
0
ファイル: imageoutput.cpp プロジェクト: Nvizible/oiio
bool ImageOutput::write_tiles (int xbegin, int xend, int ybegin, int yend,
                               int zbegin, int zend, TypeDesc format,
                               const void *data, stride_t xstride,
                               stride_t ystride, stride_t zstride)
{
    if (! m_spec.valid_tile_range (xbegin, xend, ybegin, yend, zbegin, zend))
        return false;

    // Default implementation: write each tile individually
    stride_t native_pixel_bytes = (stride_t) m_spec.pixel_bytes (true);
    if (format == TypeDesc::UNKNOWN && xstride == AutoStride)
        xstride = native_pixel_bytes;
    m_spec.auto_stride (xstride, ystride, zstride, format, m_spec.nchannels,
                        xend-xbegin, yend-ybegin);

    bool ok = true;
    stride_t pixelsize = format.size() * m_spec.nchannels;
    std::vector<char> buf;
    for (int z = zbegin;  z < zend;  z += std::max(1,m_spec.tile_depth)) {
        int zd = std::min (zend-z, m_spec.tile_depth);
        for (int y = ybegin;  y < yend;  y += m_spec.tile_height) {
            char *tilestart = ((char *)data + (z-zbegin)*zstride
                               + (y-ybegin)*ystride);
            int yh = std::min (yend-y, m_spec.tile_height);
            for (int x = xbegin;  ok && x < xend;  x += m_spec.tile_width) {
                int xw = std::min (xend-x, m_spec.tile_width);
                // Full tiles are written directly into the user buffer, but
                // Partial tiles (such as at the image edge) are copied into
                // a padded buffer to stage them.
                if (xw == m_spec.tile_width && yh == m_spec.tile_height &&
                    zd == m_spec.tile_depth) {
                    ok &= write_tile (x, y, z, format, tilestart,
                                     xstride, ystride, zstride);
                } else {
                    buf.resize (pixelsize * m_spec.tile_pixels());
                    OIIO_NAMESPACE::copy_image (m_spec.nchannels, xw, yh, zd,
                                tilestart, pixelsize, xstride, ystride, zstride,
                                &buf[0], pixelsize, pixelsize*m_spec.tile_width,
                                pixelsize*m_spec.tile_pixels());
                    ok &= write_tile (x, y, z, format, &buf[0],
                                      pixelsize, pixelsize*m_spec.tile_width,
                                      pixelsize*m_spec.tile_pixels());
                }
                tilestart += m_spec.tile_width * xstride;
            }
        }
    }
    return ok;
}
コード例 #3
0
ファイル: py_imageoutput.cpp プロジェクト: Chifoncake/oiio
bool
ImageOutputWrap::write_tile_bt (int x, int y, int z, TypeDesc::BASETYPE format,
                                object &buffer, stride_t xstride,
                                stride_t ystride, stride_t zstride)
{
    return write_tile(x, y, z, format, buffer, xstride, ystride, zstride);    
}
コード例 #4
0
ファイル: Channel.cpp プロジェクト: TannerTaphorn/datastore
TileIndex Channel::split_tile_if_needed(TileIndex ti, Tile &tile) {
  TileIndex new_root_index = TileIndex::null();
  if (tile.binary_length() <= m_max_tile_size) return new_root_index;
  Tile children[2];
  TileIndex child_indexes[2];
  if (verbosity) log_f("split_tile_if_needed: splitting tile %s", ti.to_string().c_str());

  // If we're splitting an "all" tile, it means that until now the channel has only had one tile's worth of
  // data, and that a proper root tile location couldn't be selected.  Select a new root tile now.
  if (ti.is_nonnegative_all()) {
    // TODO: this breaks if all samples are at one time
    ti = new_root_index = TileIndex::index_containing(Range(tile.first_sample_time(), tile.last_sample_time()));
    if (verbosity) log_f("split_tile_if_needed: Moving root tile to %s", ti.to_string().c_str());
  }
  
  child_indexes[0]= ti.left_child();
  child_indexes[1]= ti.right_child();

  double split_time = ti.right_child().start_time();
  split_samples(tile.double_samples, split_time, children[0], children[1]);
  split_samples(tile.string_samples, split_time, children[0], children[1]);

  for (int i = 0; i < 2; i++) {
    assert(!has_tile(child_indexes[i]));
    assert(split_tile_if_needed(child_indexes[i], children[i]) == TileIndex::null());
    write_tile(child_indexes[i], children[i]);
  }
  create_parent_tile_from_children(ti, tile, children);
  return new_root_index;
}
コード例 #5
0
ファイル: geojson.c プロジェクト: brunosan/tippecanoe
int traverse_zooms(int geomfd[4], off_t geom_size[4], char *metabase, unsigned *file_bbox, struct pool **file_keys, unsigned *midx, unsigned *midy, char **layernames, int maxzoom, int minzoom, sqlite3 *outdb, double droprate, int buffer, const char *fname, const char *tmpdir, double gamma, int nlayers, char *prevent) {
	int i;
	for (i = 0; i <= maxzoom; i++) {
		long long most = 0;

		FILE *sub[4];
		int subfd[4];
		int j;
		for (j = 0; j < 4; j++) {
			char geomname[strlen(tmpdir) + strlen("/geom2.XXXXXXXX") + 1];
			sprintf(geomname, "%s/geom%d.XXXXXXXX", tmpdir, j);
			subfd[j] = mkstemp(geomname);
			//printf("%s\n", geomname);
			if (subfd[j] < 0) {
				perror(geomname);
				exit(EXIT_FAILURE);
			}
			sub[j] = fopen(geomname, "wb");
			if (sub[j] == NULL) {
				perror(geomname);
				exit(EXIT_FAILURE);
			}
			unlink(geomname);
		}

		long long todo = 0;
		long long along = 0;
		for (j = 0; j < 4; j++) {
			todo += geom_size[j];
		}

		for (j = 0; j < 4; j++) {
			if (geomfd[j] < 0) {
				// only one source file for zoom level 0
				continue;
			}
			if (geom_size[j] == 0) {
				continue;
			}

			// printf("%lld of geom_size\n", (long long) geom_size[j]);

			char *geom = mmap(NULL, geom_size[j], PROT_READ, MAP_PRIVATE, geomfd[j], 0);
			if (geom == MAP_FAILED) {
				perror("mmap geom");
				exit(EXIT_FAILURE);
			}

			char *geomstart = geom;
			char *end = geom + geom_size[j];

			while (geom < end) {
				int z;
				unsigned x, y;

				deserialize_int(&geom, &z);
				deserialize_uint(&geom, &x);
				deserialize_uint(&geom, &y);

				// fprintf(stderr, "%d/%u/%u\n", z, x, y);

				long long len = write_tile(&geom, metabase, file_bbox, z, x, y, z == maxzoom ? full_detail : low_detail, maxzoom, file_keys, layernames, outdb, droprate, buffer, fname, sub, minzoom, maxzoom, todo, geomstart, along, gamma, nlayers, prevent);

				if (len < 0) {
					return i - 1;
				}

				if (z == maxzoom && len > most) {
					*midx = x;
					*midy = y;
					most = len;
				}
			}

			if (munmap(geomstart, geom_size[j]) != 0) {
				perror("munmap geom");
			}
			along += geom_size[j];
		}

		for (j = 0; j < 4; j++) {
			close(geomfd[j]);
			fclose(sub[j]);

			struct stat geomst;
			if (fstat(subfd[j], &geomst) != 0) {
				perror("stat geom\n");
				exit(EXIT_FAILURE);
			}

			geomfd[j] = subfd[j];
			geom_size[j] = geomst.st_size;
		}
	}

	fprintf(stderr, "\n");
	return maxzoom;
}
コード例 #6
0
ファイル: Channel.cpp プロジェクト: TannerTaphorn/datastore
void Channel::create_tile(TileIndex ti) {
  Tile tile;
  write_tile(ti, tile);
}
コード例 #7
0
ファイル: Channel.cpp プロジェクト: TannerTaphorn/datastore
void Channel::add_data_internal(const std::vector<DataSample<T> > &data, DataRanges *channel_ranges) {
  if (!data.size()) return;
  // Sanity check
  if (data[0].time < 0) throw std::runtime_error("Unimplemented feature: adding data with negative time");
  for (unsigned i = 0; i < data.size()-1; i++) {
    if (data[i].time > data[i+1].time) throw std::runtime_error("Attempt to add data that is not sorted by ascending time");
  }

  //	regenerate = empty set
  Locker lock(*this);  // Lock self and hold lock until exiting this method
  std::set<TileIndex> to_regenerate;

  ChannelInfo info;
  bool success = read_info(info);
  if (!success) {
    // New channel
    info.magic = ChannelInfo::MAGIC;
    info.version = 0x00010000;
    info.times = Range(data[0].time, data.back().time);
    info.nonnegative_root_tile_index = TileIndex::nonnegative_all();
    create_tile(TileIndex::nonnegative_all());
    info.negative_root_tile_index = TileIndex::null();
  } else {
    info.times.add(Range(data[0].time, data.back().time));
    // If we're not the all-tile, see if we need to move the root upwards
    if (info.nonnegative_root_tile_index != TileIndex::nonnegative_all()) {
      TileIndex new_nonnegative_root_tile_index = TileIndex::index_containing(info.times);
      if (new_nonnegative_root_tile_index.level > info.nonnegative_root_tile_index.level) {
	// Root index changed.  Confirm new root is parent or more distant ancestor of old root
	assert(new_nonnegative_root_tile_index.is_ancestor_of(info.nonnegative_root_tile_index));
	// Trigger regeneration from old root's parent, up through new root
	to_regenerate.insert(info.nonnegative_root_tile_index.parent());
	move_root_upwards(new_nonnegative_root_tile_index, info.nonnegative_root_tile_index);
	info.nonnegative_root_tile_index = new_nonnegative_root_tile_index;
      }
    }
  }

  unsigned i=0;

  while (i < data.size()) {
    TileIndex ti= find_lowest_child_overlapping_time(info.nonnegative_root_tile_index, data[i].time);
    assert(!ti.is_null());

    Tile tile;
    assert(read_tile(ti, tile));
    const DataSample<T> *begin = &data[i];
    while (i < data.size() && ti.contains_time(data[i].time)) i++;
    const DataSample<T> *end = &data[i];
    tile.insert_samples(begin, end);
    
    TileIndex new_root = split_tile_if_needed(ti, tile);
    if (new_root != TileIndex::null()) {
      assert(ti == TileIndex::nonnegative_all());
      if (verbosity) log_f("Channel: %s changing root from %s to %s",
                           descriptor().c_str(), ti.to_string().c_str(),
                           new_root.to_string().c_str());
      info.nonnegative_root_tile_index = new_root;
      delete_tile(ti); // Delete old root
      ti = new_root;
    }
    write_tile(ti, tile);
    if (ti == info.nonnegative_root_tile_index && channel_ranges) { *channel_ranges = tile.ranges; }
    if (ti != info.nonnegative_root_tile_index) to_regenerate.insert(ti.parent());
  }
  
  // Regenerate from lowest level to highest
  while (!to_regenerate.empty()) {
    TileIndex ti = *to_regenerate.begin();
    to_regenerate.erase(to_regenerate.begin());
    Tile regenerated, children[2];
    assert(read_tile(ti.left_child(), children[0]));
    assert(read_tile(ti.right_child(), children[1]));
    create_parent_tile_from_children(ti, regenerated, children);
    write_tile(ti, regenerated);
    if (ti == info.nonnegative_root_tile_index && channel_ranges) { *channel_ranges = regenerated.ranges; }
    if (ti != info.nonnegative_root_tile_index) to_regenerate.insert(ti.parent());
  }
  write_info(info);
}
コード例 #8
0
ファイル: imageoutput.cpp プロジェクト: angeljimenez/oiio
bool
ImageOutput::write_image (TypeDesc format, const void *data,
                          stride_t xstride, stride_t ystride, stride_t zstride,
                          ProgressCallback progress_callback,
                          void *progress_callback_data)
{
    bool native = (format == TypeDesc::UNKNOWN);
    stride_t pixel_bytes = (stride_t) m_spec.pixel_bytes (native);
    if (native && xstride == AutoStride)
        xstride = pixel_bytes;
    m_spec.auto_stride (xstride, ystride, zstride, format,
                        m_spec.nchannels, m_spec.width, m_spec.height);
    if (supports ("rectangles")) {
        // Use a rectangle if we can
        return write_rectangle (0, m_spec.width-1, 0, m_spec.height-1, 0, m_spec.depth-1,
                                format, data, xstride, ystride, zstride);
    }

    bool ok = true;
    if (progress_callback)
        if (progress_callback (progress_callback_data, 0.0f))
            return ok;
    if (m_spec.tile_width && supports ("tiles")) {
        // Tiled image

        // FIXME: what happens if the image dimensions are smaller than
        // the tile dimensions?  Or if one of the tiles runs past the
        // right or bottom edge?  Do we need to allocate a full tile and
        // copy into it before calling write_tile?  That's probably the
        // safe thing to do.  Or should that handling be pushed all the
        // way into write_tile itself?

        // Locally allocate a single tile to gracefully deal with image
        // dimensions smaller than a tile, or if one of the tiles runs
        // past the right or bottom edge.  Then we copy from our tile to
        // the user data, only copying valid pixel ranges.
        size_t tilexstride = pixel_bytes;
        size_t tileystride = tilexstride * m_spec.tile_width;
        size_t tilezstride = tileystride * m_spec.tile_height;
        size_t tile_pixels = (size_t)m_spec.tile_width * (size_t)m_spec.tile_height *
            (size_t)std::max(1,m_spec.tile_depth);
        std::vector<char> pels (tile_pixels * pixel_bytes);
        for (int z = 0;  z < m_spec.depth;  z += m_spec.tile_depth)
            for (int y = 0;  y < m_spec.height;  y += m_spec.tile_height) {
                for (int x = 0;  x < m_spec.width && ok;  x += m_spec.tile_width) {
                    // Now copy out the scanlines
                    // FIXME -- can we do less work for the tiles that
                    // don't overlap image boundaries?
                    int ntz = std::min (z+m_spec.tile_depth, m_spec.depth) - z;
                    int nty = std::min (y+m_spec.tile_height, m_spec.height) - y;
                    int ntx = std::min (x+m_spec.tile_width, m_spec.width) - x;
                    for (int tz = 0;  tz < ntz;  ++tz) {
                        for (int ty = 0;  ty < nty;  ++ty) {
                            // FIXME -- doesn't work for non-contiguous scanlines
                            memcpy (&pels[ty*tileystride+tz*tilezstride],
                                    (char *)data + x*xstride + (y+ty)*ystride + (z+tz)*zstride,
                                    ntx*tilexstride);
                        }
                    }

                    ok &= write_tile (x+m_spec.x, y+m_spec.y, z+m_spec.z,
                                      format, &pels[0]);
                }
                if (progress_callback)
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    } else {
        // Scanline image
        for (int z = 0;  z < m_spec.depth;  ++z)
            for (int y = 0;  y < m_spec.height && ok;  ++y) {
                ok &= write_scanline (y+m_spec.y, z+m_spec.z, format,
                                      (const char *)data + z*zstride + y*ystride,
                                      xstride);
                if (progress_callback && !(y & 0x0f))
                    if (progress_callback (progress_callback_data, (float)y/m_spec.height))
                        return ok;
            }
    }
    if (progress_callback)
        progress_callback (progress_callback_data, 1.0f);

    return ok;
}