{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7d84d0c7-8625-432c-acd7-89bdb0e66a43",
   "metadata": {},
   "outputs": [],
   "source": [
    "from osgeo import gdal\n",
    "import os\n",
    "\n",
    "def crop_raster(input_raster_path, output_raster_path, bounds):\n",
    "    \"\"\"\n",
    "    使用 GDAL 裁剪栅格影像到指定的四至范围。\n",
    "\n",
    "    :param input_raster_path: 输入栅格影像路径\n",
    "    :param output_raster_path: 输出裁剪后影像的路径\n",
    "    :param bounds: 裁剪范围，格式为 (minx, miny, maxx, maxy)\n",
    "    \"\"\"\n",
    "    minx, miny, maxx, maxy = bounds\n",
    "\n",
    "    # 打开输入影像\n",
    "    dataset = gdal.Open(input_raster_path)\n",
    "    if dataset is None:\n",
    "        print(f\"无法打开输入影像: {input_raster_path}\")\n",
    "        return\n",
    "\n",
    "    # 获取影像的投影和变换信息\n",
    "    geo_transform = dataset.GetGeoTransform()\n",
    "    projection = dataset.GetProjection()\n",
    "\n",
    "    # 计算裁剪区域在影像中的像素坐标\n",
    "    ulx = int((minx - geo_transform[0]) / geo_transform[1])  # 左上角 x\n",
    "    uly = int((maxy - geo_transform[3]) / geo_transform[5])  # 左上角 y\n",
    "    lrx = int((maxx - geo_transform[0]) / geo_transform[1])  # 右下角 x\n",
    "    lry = int((miny - geo_transform[3]) / geo_transform[5])  # 右下角 y\n",
    "\n",
    "    # 检查像素坐标是否在影像范围内\n",
    "    if ulx < 0 or uly < 0 or lrx > dataset.RasterXSize or lry > dataset.RasterYSize:\n",
    "        print(\"裁剪范围超出影像范围！\")\n",
    "        return\n",
    "\n",
    "    # 创建输出影像\n",
    "    driver = gdal.GetDriverByName('GTiff')\n",
    "    out_dataset = driver.Create(output_raster_path, lrx - ulx, lry - uly, dataset.RasterCount, gdal.GDT_Float32)\n",
    "\n",
    "    # 设置输出影像的投影和变换信息\n",
    "    out_geo_transform = (minx, geo_transform[1], geo_transform[2], maxy, geo_transform[4], geo_transform[5])\n",
    "    out_dataset.SetGeoTransform(out_geo_transform)\n",
    "    out_dataset.SetProjection(projection)\n",
    "\n",
    "    # 将裁剪后的数据写入输出影像\n",
    "    for i in range(1, dataset.RasterCount + 1):\n",
    "        band = dataset.GetRasterBand(i)\n",
    "        data = band.ReadAsArray(ulx, uly, lrx - ulx, lry - uly)\n",
    "        out_dataset.GetRasterBand(i).WriteArray(data)\n",
    "\n",
    "    # 清理\n",
    "    out_dataset.FlushCache()\n",
    "    del out_dataset\n",
    "    del dataset\n",
    "\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3ac1f4a3-38f8-4c50-8bad-36852fcb18f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 输入栅格影像路径\n",
    "input_raster = \"115E39N_COP30.tif\"\n",
    "\n",
    "# 输出裁剪后影像的路径\n",
    "output_raster = \"115E39N_COP30_clip.tif\"\n",
    "\n",
    "\n",
    "# 定义裁剪范围 (minx, miny, maxx, maxy)\n",
    "bounds =(115.5,43.5,117.0,45.0)  # 示例范围\n",
    "\n",
    "# 裁剪影像\n",
    "crop_raster(input_raster, output_raster, bounds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "65dcf0f1-55e7-4dfa-8988-412ca0e6c41a",
   "metadata": {},
   "outputs": [],
   "source": [
    "(xmin, ymin, xmax, ymax)=(115.5,43.5,117.0,45.0)\n",
    "# 定义裁剪范围 (minx, miny, maxx, maxy)\n",
    "bounds = (xmin, ymin, xmax, ymax)  # 例如 (100000, 200000, 110000, 210000)\n",
    "# 裁剪影像\n",
    "clip_raster(input_raster, output_raster, bounds)\n",
    "print(f\"影像已裁剪并保存到: {output_raster}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea8bcfa3-7612-477d-bf0b-b4e3537fcf33",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "407416e7-729d-4d7e-ae09-318cdfce7739",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
