regionator.cc
// Recursively splits the tiles into sub-quandrants.
Recursively splits the tiles into sub-quandrants.
Recursively splits the tiles into sub - quandrants .
void Regionator::SplitTileRecursively(int level, int x1, int y1,
                                      int x2, int y2) const {
  Image subimage;
  if (!subimage.Resize(x_tile_size_, y_tile_size_, Image::RGBA)) {
    fprintf(stderr, "\nCan't resize subimage\n");
    exit(EXIT_FAILURE);
  }
  double dx = static_cast<double>(x2 - x1) /
              static_cast<double>(subimage.width() - 1);
  double dy = static_cast<double>(y2 - y1) /
              static_cast<double>(subimage.height() - 1);
  Color pixel(4);
  Color transparent(4);
  transparent.SetAllChannels(0);
  bool is_transparent = true;
  bool is_opaque = true;
  for (int i = 0; i < subimage.width(); ++i) {
    int x = Min(static_cast<int>(x1 + i * dx + 0.5), x2);
    for (int j = 0; j < subimage.height(); ++j) {
      int y = Min(static_cast<int>(y1 + j * dy + 0.5), y2);
      if (x >= image_->width() || y >= image_->height()) {
        subimage.SetPixel(i, j, transparent);
        is_opaque = false;
      } else {
        image_->GetPixel(x, y, &pixel);
        subimage.SetPixel(i, j, pixel);
        if (pixel.GetChannel(3) != 0) {
          is_transparent = false;
        }
        if (pixel.GetChannel(3) != 255) {
          is_opaque = false;
        }
      }
    }
  }
  if (is_opaque) {
    if (!subimage.ConvertToRGB()) {
      fprintf(stderr, "\nCan't convert subimage to RGB\n");
      exit(EXIT_FAILURE);
    }
  }
  string prefix = MakeFilenamePrefix(x1, y1, x2, y2);
  string filename = prefix + ".png";
  string kml_filename = prefix + ".kml";
  string full_filename = output_directory_ + "/" + filename;
  string full_kml_filename = output_directory_ + "/" + kml_filename;
  if (!subimage.Write(full_filename)) {
    fprintf(stderr, "\nCan't write image '%s' to file\n",
            full_filename.c_str());
    exit(EXIT_FAILURE);
  }
  subimage.Clear();
  double north;
  double south;
  double east;
  double west;
  ComputeBoundingBox(x1, y1, x2, y2, &north, &south, &east, &west);
  KmlLatLonAltBox lat_lon_alt_box;
  lat_lon_alt_box.north.set(north);
  lat_lon_alt_box.south.set(south);
  lat_lon_alt_box.east.set(east);
  lat_lon_alt_box.west.set(west);
  KmlLod lod;
  if (level == 0) {
    lod.min_lod_pixels.set(0);
    lod.max_lod_pixels.set(-1);
  } else {
    lod.min_lod_pixels.set(min_lod_pixels_);
    lod.max_lod_pixels.set(max_lod_pixels_);
  }
  KmlRegion region;
  region.lat_lon_alt_box.set(lat_lon_alt_box);
  region.lod.set(lod);
  KmlIcon icon;
  icon.href.set(filename);
  KmlGroundOverlay ground_overlay;
  ground_overlay.draw_order.set(level + top_level_draw_order_);
  ground_overlay.icon.set(icon);
  ground_overlay.lat_lon_box.set(lat_lon_alt_box);
  Kml kml;
  kml.region.set(region);
  kml.AddGroundOverlay(ground_overlay);
  if (draw_tile_borders_) {
    KmlLineString line_string;
    line_string.AddCoordinate(east, north);
    line_string.AddCoordinate(west, north);
    line_string.AddCoordinate(west, south);
    line_string.AddCoordinate(east, south);
    line_string.AddCoordinate(east, north);
    KmlPlacemark placemark;
    placemark.line_string.set(line_string);
    kml.AddPlacemark(placemark);
  }
  if (x2 - x1 <= x_tile_size_ || y2 - y1 <= y_tile_size_ || is_transparent) {
  } else {
    int xmid = (x1 + x2) / 2;
    int ymid = (y1 + y2) / 2;
    KmlNetworkLink ul = MakeNetworkLink(x1, y1, xmid, ymid);
    KmlNetworkLink ur = MakeNetworkLink(xmid, y1, x2, ymid);
    KmlNetworkLink ll = MakeNetworkLink(x1, ymid, xmid, y2);
    KmlNetworkLink lr = MakeNetworkLink(xmid, ymid, x2, y2);
    kml.AddNetworkLink(ul);
    kml.AddNetworkLink(ur);
    kml.AddNetworkLink(ll);
    kml.AddNetworkLink(lr);
    SplitTileRecursively(level + 1, x1, y1, xmid, ymid);  
    SplitTileRecursively(level + 1, xmid, y1, x2, ymid);  
    SplitTileRecursively(level + 1, x1, ymid, xmid, y2);  
    SplitTileRecursively(level + 1, xmid, ymid, x2, y2);  
  }
  FILE *fp = fopen(full_kml_filename.c_str(), "w");
  if (!fp) {
    fprintf(stderr, "Can't open file '%s' for writing\n",
            full_kml_filename.c_str());
    exit(EXIT_FAILURE);
  }
  fprintf(fp, "%s", kml.ToString().c_str());
  fclose(fp);
}
void Regionator :: SplitTileRecursively ( int level , int x1 , int y1 , int x2 , int y2 ) const { Image subimage ; if ( ! subimage . Resize ( x_tile_size_ , y_tile_size_ , Image :: RGBA ) ) { fprintf ( stderr , " \n \n " ) ; exit ( EXIT_FAILURE ) ; } double dx = static_cast < double > ( x2 - x1 ) / static_cast < double > ( subimage . width ( ) - 1 ) ; double dy = static_cast < double > ( y2 - y1 ) / static_cast < double > ( subimage . height ( ) - 1 ) ; Color pixel ( 4 ) ; Color transparent ( 4 ) ; transparent . SetAllChannels ( 0 ) ; bool is_transparent = true ; bool is_opaque = true ; for ( int i = 0 ; i < subimage . width ( ) ; ++ i ) { int x = Min ( static_cast < int > ( x1 + i * dx + 0.5 ) , x2 ) ; for ( int j = 0 ; j < subimage . height ( ) ; ++ j ) { int y = Min ( static_cast < int > ( y1 + j * dy + 0.5 ) , y2 ) ; if ( x >= image_ -> width ( ) || y >= image_ -> height ( ) ) { subimage . SetPixel ( i , j , transparent ) ; is_opaque = false ; } else { image_ -> GetPixel ( x , y , & pixel ) ; subimage . SetPixel ( i , j , pixel ) ; if ( pixel . GetChannel ( 3 ) != 0 ) { is_transparent = false ; } if ( pixel . GetChannel ( 3 ) != 255 ) { is_opaque = false ; } } } } if ( is_opaque ) { if ( ! subimage . ConvertToRGB ( ) ) { fprintf ( stderr , " \n \n " ) ; exit ( EXIT_FAILURE ) ; } } string prefix = MakeFilenamePrefix ( x1 , y1 , x2 , y2 ) ; string filename = prefix + " " ; string kml_filename = prefix + " " ; string full_filename = output_directory_ + " " + filename ; string full_kml_filename = output_directory_ + " " + kml_filename ; if ( ! subimage . Write ( full_filename ) ) { fprintf ( stderr , " \n \n " , full_filename . c_str ( ) ) ; exit ( EXIT_FAILURE ) ; } subimage . Clear ( ) ; double north ; double south ; double east ; double west ; ComputeBoundingBox ( x1 , y1 , x2 , y2 , & north , & south , & east , & west ) ; KmlLatLonAltBox lat_lon_alt_box ; lat_lon_alt_box . north . set ( north ) ; lat_lon_alt_box . south . set ( south ) ; lat_lon_alt_box . east . set ( east ) ; lat_lon_alt_box . west . set ( west ) ; KmlLod lod ; if ( level == 0 ) { lod . min_lod_pixels . set ( 0 ) ; lod . max_lod_pixels . set ( -1 ) ; } else { lod . min_lod_pixels . set ( min_lod_pixels_ ) ; lod . max_lod_pixels . set ( max_lod_pixels_ ) ; } KmlRegion region ; region . lat_lon_alt_box . set ( lat_lon_alt_box ) ; region . lod . set ( lod ) ; KmlIcon icon ; icon . href . set ( filename ) ; KmlGroundOverlay ground_overlay ; ground_overlay . draw_order . set ( level + top_level_draw_order_ ) ; ground_overlay . icon . set ( icon ) ; ground_overlay . lat_lon_box . set ( lat_lon_alt_box ) ; Kml kml ; kml . region . set ( region ) ; kml . AddGroundOverlay ( ground_overlay ) ; if ( draw_tile_borders_ ) { KmlLineString line_string ; line_string . AddCoordinate ( east , north ) ; line_string . AddCoordinate ( west , north ) ; line_string . AddCoordinate ( west , south ) ; line_string . AddCoordinate ( east , south ) ; line_string . AddCoordinate ( east , north ) ; KmlPlacemark placemark ; placemark . line_string . set ( line_string ) ; kml . AddPlacemark ( placemark ) ; } if ( x2 - x1 <= x_tile_size_ || y2 - y1 <= y_tile_size_ || is_transparent ) { } else { int xmid = ( x1 + x2 ) / 2 ; int ymid = ( y1 + y2 ) / 2 ; KmlNetworkLink ul = MakeNetworkLink ( x1 , y1 , xmid , ymid ) ; KmlNetworkLink ur = MakeNetworkLink ( xmid , y1 , x2 , ymid ) ; KmlNetworkLink ll = MakeNetworkLink ( x1 , ymid , xmid , y2 ) ; KmlNetworkLink lr = MakeNetworkLink ( xmid , ymid , x2 , y2 ) ; kml . AddNetworkLink ( ul ) ; kml . AddNetworkLink ( ur ) ; kml . AddNetworkLink ( ll ) ; kml . AddNetworkLink ( lr ) ; SplitTileRecursively ( level + 1 , x1 , y1 , xmid , ymid ) ; SplitTileRecursively ( level + 1 , xmid , y1 , x2 , ymid ) ; SplitTileRecursively ( level + 1 , x1 , ymid , xmid , y2 ) ; SplitTileRecursively ( level + 1 , xmid , ymid , x2 , y2 ) ; } FILE * fp = fopen ( full_kml_filename . c_str ( ) , " " ) ; if ( ! fp ) { fprintf ( stderr , " \n " , full_kml_filename . c_str ( ) ) ; exit ( EXIT_FAILURE ) ; } fprintf ( fp , " " , kml . ToString ( ) . c_str ( ) ) ; fclose ( fp ) ; }
Recursively splits the tiles into sub-quandrants.
Recursively splits the tiles into sub - quandrants .
// Generate an scaled down version of the image over the given bounding // box to be of size tile_side_length_ x tile_side_length_. // Copy the relevant pixels from the input image for the scaled down version. // Use simple point sampling since Earth applies its own filtering. // We keep track of empty regions so that we don't recurse further // than is necessary. // We keep track of opaque regions so that we can compress the tile // by converting to RGB. // Convert opaque tiles to RGB.  This saves some disk space (probably not // much), but more importantly it allows us to easily know which tiles we // can safely convert to JPEG later. // Write tile to file. // We no longer need the memory from this tile, so we clean it up now to // avoid recursing with unnecessary memory allocation. // Compute the bounding box for this image. // This KML describes the current image and it's region. // The tile coverting the entire image should always be visible. // Other subtiles use the user specified Lod values. // Set the drawOrder of the finer grain tiles higher such that they are // drawn on top of the lower res tiles.  Note that all tiles in a given // level will have the same drawOrder. // Draw a border around this image. // The base case has occured: the image has been processed down to the // desired resolution or the current tile is completely transparent. // NB: We use x2 - x1 instead of x2 - x1 + 1 (the true tile width) because // there is a 1 pixel overlap between adjacent quads. // Recursively process each quadrant of this quadrant. // Add the 4 subregions to the KML. // Upper left quad // Upper right quad // Lower left quad // Lower right quad