2011-09-07 8 views
6

Tôi có một thường lệ procedure DrawStuff(ACanvas: TCanvas; const ARect: TRect) vẽ thứ gì đó vào hình chữ nhật được chỉ định trên một TCanvas. Tại thời điểm này tôi gọi DrawStuff bằng canvas của PaintBox. Bây giờ tôi đang thêm một tùy chọn Save as, trong đó người dùng có thể chọn từ nhiều định dạng tệp khác nhau (bmp, wmf, jpg, ... - thích hợp nhất với nhiều hậu duệ TGraphic) để lưu kết quả của DrawStuff vào .Lưu hình ảnh vào nhiều định dạng tệp khác nhau

Vẽ đến TMetafile và lưu thành "bla.bmp" hoặc Assign nhập vào TPicture không hoạt động chính xác - ví dụ: nó tạo ra các tệp có phần mở rộng ".bmp" mà không phải là bitmap. Ngay bây giờ tôi không thể tìm ra giải pháp không liên quan đến vỏ bọc đặc biệt ở mỗi định dạng tệp đơn lẻ:

  • bmp - Sử dụng TBitmap.Canvas.
  • wmf/emf: Sử dụng TMetafileCanvas.
  • v.v.

Bạn có biết ý kiến ​​nào cho tôi không?

+2

Nó rất dễ dàng để làm cho một thói quen 'thống nhất' để tiết kiệm BMP, PNG, GIF, JPG, vv, nhưng nó là khó khăn hơn để làm điều đó nếu nó cũng bao gồm WMF hoặc EMF, vì sau này là * định dạng hình ảnh vector *, trong khi định dạng cũ là * định dạng hình ảnh raster. Trừ khi, tất nhiên, bạn chọn lưu hình ảnh dưới dạng bitmap raster được nhúng trong EMF/WMF của bạn, nhưng trong trường hợp đó, nó là ngu ngốc khi sử dụng định dạng EMF/WMF ... –

+0

Đặc biệt vỏ wmf/emf Sẽ ổn thôi. Bạn có thể đưa cho tôi con trỏ đến thói quen thống nhất mà bạn đề cập không? –

+0

PS: Tôi nghĩ vẽ lên một tệp siêu dữ liệu và sau đó 'Gán' cho nó thành' TPicture' có thể hoạt động như một bộ sưu tập các cuộc gọi GDI đã ghi. –

Trả lời

9

Tôi đoán một sự chuyển đổi "câm" có lẽ cũng đơn giản như thế này:

type 
    TGraphicTypeEnum = (gteBMP, gteJPG, gteTIF, gtePNG); 

procedure SaveGraphicAs(AGraphic : TGraphic; AGraphicType : TGraphicTypeEnum; AFileName : String); 
var vGraphicClass : TGraphicClass; 
    vTargetGraphic : TGraphic; 
    vBmp : TBitmap; 
begin 

    case AGraphicType of 
    gteBMP : vGraphicClass := TBitmap; 
    gtejpg : vGraphicClass := TJPEGImage; 
    gtetif : vGraphicClass := TWICImage; 
    gtepng : vGraphicClass := TPngImage; 
    else 
    // EXIT; or raise... 
    end; 
    if aGraphic is vGraphicClass then //As suggested by Rob Kennedy 
    AGraphic.SaveToFile(AFileName) 
    else 
    begin 
    vBmp := nil; 
    vTargetGraphic := vGraphicClass.Create; 
    try 
     vBmp := TBitmap.Create; 
     vBmp.Assign(AGraphic); 
     vTargetGraphic.Assign(vBmp); 
     vTargetGraphic.SaveToFile(aFileName); 
    finally 
     vTargetGraphic.Free; 
     vBmp.Free; 
    end; 
    end; 
end; 

Gán một TPicture đã không làm việc, như khi bạn gán cho một TPicture, TPicture sẽ chuyển đổi đồ họa đến lớp bạn đang chỉ định từ.

Lưu ý rằng trong ví dụ của tôi, có 2 lớp chuyển đổi khi hình ảnh gốc được chuyển thành bitmap trước khi được chuyển đổi sang định dạng cuối cùng. Có thể có khá nhiều mất thông tin trong quá trình này. Hầu hết (tất cả?) Loại đồ họa biết cách chuyển đổi sang và từ TBitmap, nhưng TJPEGImage không biết cách chuyển đổi sang TPngImage và ngược lại.

Phương pháp chuyển đổi hiệu quả hơn có thể được phát triển giữ tính minh bạch và các hiệu ứng khác cụ thể cho định dạng tệp, nhưng đó là kiến ​​thức của tôi. Nhưng tùy theo nhu cầu của bạn, điều đó có thể là đủ.

+0

Có thể đáng để kiểm tra 'nếu Agraphic là vGraphicClass' và bỏ qua chuyển đổi bitmap nếu nó đúng. Nếu không, bạn sẽ mất chất lượng hình ảnh ngay cả khi lưu JPEG dưới dạng JPEG. –

+0

Hoặc bỏ qua gọi hàm SaveGraphicAs và chỉ cần gọi AGraphic.SaveToFile. Có một số vấn đề khác có thể cắt ra. Một bên thứ 3 có thể đăng ký lớp PNG của riêng họ (DevExpress làm điều đó). Vì vậy, bạn sẽ kết thúc với 'TdxPNGImage là TPNGImage' (Mà sẽ là sai). Thật không may là không thể thực hiện vào lúc này để có được lớp học đã đăng ký hiện tại cho một phần mở rộng nhất định (QC57402 được yêu cầu vào 2008-01-24 ... Vẫn mở). Nó có thể dễ dàng hơn cho người gọi để tìm ra nếu đồ họa đã ở định dạng thích hợp. Nhưng yeah, tôi đoán nó sẽ không làm tổn thương để làm cho rằng tối ưu hóa. –