gen-preview.cjs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. const { fromFile } = require('geotiff')
  2. const sharp = require('sharp')
  3. const fs = require('fs')
  4. const path = require('path')
  5. async function main() {
  6. const tiffPath = path.resolve(__dirname, '../de99928f1689454084d1af33ec3cc155.tif')
  7. const outPath = path.resolve(__dirname, '../public/de99928f-preview.png')
  8. if (!fs.existsSync(tiffPath)) {
  9. console.error('TIFF not found:', tiffPath)
  10. process.exit(1)
  11. }
  12. console.log('Reading TIFF...')
  13. const tiff = await fromFile(tiffPath)
  14. const image = await tiff.getImage()
  15. const w = image.getWidth()
  16. const h = image.getHeight()
  17. console.log('TIFF size:', w, 'x', h)
  18. // 控制生成纹理尺寸:原图 14997x19876 太大,浏览器加载 123MB PNG 容易失败。
  19. // 4096 宽按原比例缩放后约 5425 高,文件体积降到 1/4 左右,仍然足够清晰。
  20. const targetW = 4096
  21. const targetH = Math.round(targetW * h / w)
  22. console.log('Target size:', targetW, 'x', targetH)
  23. console.log('Reading rasters at target size...')
  24. const data = await image.readRasters({ width: targetW, height: targetH, samples: [0, 1, 2] })
  25. const r = data[0]
  26. const g = data[1]
  27. const b = data[2]
  28. console.log('Building RGBA with alpha mask...')
  29. const rgba = Buffer.alloc(targetW * targetH * 4)
  30. let blackCount = 0
  31. for (let i = 0; i < targetW * targetH; i++) {
  32. const isBlack = r[i] < 10 && g[i] < 10 && b[i] < 10
  33. rgba[i * 4] = r[i]
  34. rgba[i * 4 + 1] = g[i]
  35. rgba[i * 4 + 2] = b[i]
  36. rgba[i * 4 + 3] = isBlack ? 0 : 255
  37. if (isBlack) blackCount++
  38. }
  39. console.log('Black pixels masked:', blackCount)
  40. await sharp(rgba, { raw: { width: targetW, height: targetH, channels: 4 } })
  41. .png({ compressionLevel: 9, adaptiveFiltering: true })
  42. .toFile(outPath)
  43. console.log('Saved:', outPath)
  44. }
  45. main().catch(e => {
  46. console.error(e)
  47. process.exit(1)
  48. })