Vinova tuyển lập trình viên Mobile & Web ở Hà Nội, lương $300-1000

Article: Chụp màn hình OpenGL thành phim 1384

ngocdaothanh.myopenid.com 172
Updated over 3 years ago

Khi viết chương trình OpenGL xong, muốn chụp màn hình lại thành ảnh tĩnh ta dùng phím PrintScreen, muốn chụp thành phim thường ta dùng chương trình đại loại như iShowU. Tuy nhiên cách khác là tự xử lí ngay trong chương trình OpenGL của mình. Bài viết này sẽ cho thấy cách này đơn giản không kém vì chỉ cần thêm vài dòng mã.

Qui trình

  1. Sau khi vẽ ra màn hình, trước khi swap buffer ta dùng hàm glReadPixels để chụp lại màn hình OpenGL ra mảng byte theo thứ tự màu RGB ứng với mỗi điểm ảnh.
  2. Ghi mảng byte này thành tập tin .ppm trên đĩa. Tập tin .ppm có 2 kiểu: plain text và binary, ta dùng kiểu binary.
  3. Dùng chương trình ffmpeg để gom các tập tin .ppm thành phim.

Có thể xử lí cao cấp hơn là dùng thẳng thư viện encode video như libffmpeg để chuyển thẳng mảng byte thành phim. Trên Mac OS còn có thêm lựa chọn khác là có thể dùng thư viện QuickTime để chuyển thành phim .mov, có rất nhiều ví dụ ở developer.apple.com.

Ví dụ

Ta sẽ chụp màn hình của bài NeHe số 36 thành phim. Để đơn giản, ta dùng ruby-opengl, nó có sẵn bài này. Ta thêm vài dòng sau trước glutSwapBuffers:

  frame = glReadPixels(0, 0, 640, 480, GL_RGB, GL_UNSIGNED_BYTE)
@iframe = 0 unless @iframe
filename = sprintf('%03d.ppm', @iframe)
File.open(filename, 'wb') { |f| f.write("P6\n#{640} #{480}\n255\n"); f.write(frame) }
print "#{@iframe} "
@iframe += 1

Chạy chương trình để thu được các tập tin .ppm, rồi chạy lệnh:

ffmpeg -r 60 -qscale 1 -i %03d.ppm movie.avi

để thu được phim.

Có vài điểm cần cải tiến thêm, đây là bài tập nhỏ dành cho độc giả:

  •   Nên tính toán chính xác frame rate thay vì chỉ định số 60 như trên. Hơn nữa mắt người chỉ cần khoảng 30 frame/giây là đủ, không cần ghi ra quá nhiều tập tin như trên.
  • Ảnh thu từ hàm glReadPixels bị lộn ngược theo hướng trên dưới, cần đảo lại.

Ghi chú cho OpenGL ES

OpenGL ES dùng cho thiết bị di động, như iPhone. OpenGL ES cũng có hàm glReadPixels, nhưng có thể không hoạt động với tham số GL_RGB như trong ví dụ trên. Khi chuyển thành GL_RGBA hoặc GL_BGRA thì có thể nó lại hoạt động tốt. Tất nhiên lúc này cần xử lí thêm để loại bỏ kênh A, đổi lại thành RGB trước khi ghi ra đĩa.

Comments

You must login to be able to comment

Uploaded files

No file uploaded yet

You must login to be able to upload

Nhà tài trợ:

Mọi người đều tự do viết bài, sửa bài của người khác, và bình luận ở trang web này. Bạn muốn chủ động tạo bài mới để chia sẻ kinh nghiệm với mọi người? Xin click link ở dưới.

Create new content