|
|
#1
|
|||
|
|||
TJPegImage
Всем доброго!
Возник вопрос: Код:
procedure TForm1.CheckBox1Click(Sender: TObject); var jpeg : TJpegImage; begin jpeg := TJpegImage.Create; jpeg.Assign(ImageIn.picture.graphic); jpeg.Grayscale := checkbox1.Checked; ImageOut.Picture.Graphic.Assign(jpeg); jpeg.Destroy; end; Всё нормально - картинка сереет и цветнеет при постановке/снятии галочки. Код:
procedure TForm1.TrackBar1Change(Sender: TObject); var jpg : TJpegImage; begin Edit1.Text := IntTostr(TrackBar1.Position); jpg := TJpegImage.Create; jpg.Assign(ImageIn.picture.graphic); jpg.CompressionQuality := TrackBar1.Position; jpg.DIBNeeded; jpg.Compress; // jpg.SaveToFile('D:\Out.jpg'); ImageOut.Picture.Graphic.Assign(jpg); end; мотаю ползунком - качество картинки не меняется (при этом в файл сохраняется скомпрессованная картинка). Что не так? |
#2
|
||||
|
||||
Цитата:
Схема примерно такая: При загрузке jpeg-картинки очищаются оба буфера и в JPEG-буфер загружается jpeg-картинка. Когда есть нужда прорисовать картинку (например в TImage), то запрашивается DIB-буфер, а если он пустой, то вызывается метод DIBNeeded, который распаковывает картинку из JPEG-буфера в DIB-буфер. Когда вызываем метод Compress то DIB-буфер упаковывается в JPEG-буфер, но для отображения всё равно продолжает использоваться DIB-буфер, который после Compress совершенно не изменился. Вот если бы можно было убить DIB-буфер, то при следующем запросе из JPEG-буфер распаковалось бы новое (пережатое) содержимое. Но если для создания DIB-буфера есть соответствующий метод (DIBNeeded), то для его разрушения к сожалению нет. Точнее такой метод есть. Называется он FreeBitmap, но он почему-то скрыт в protected секции и для обычного использования недоступен. Но зато он доступен, для наследников TJPEGImage из чего вытекает такой полухакерский способ: Объявляем наследника TJPEGImage следующим образом: Код:
type TMyJpegImage = class(TJPEGImage); Код:
procedure TForm1.TrackBar1Change(Sender: TObject); var jpg : TJpegImage; begin ... jpg.Compress; TMyJpegImage(jpg).FreeBitmap; // jpg.SaveToFile('D:\Out.jpg'); ImageOut.Picture.Graphic.Assign(jpg); end; Но к счастью есть более легальный способ очистить DIB-буфер. Дело в том, что установка некоторых свойств (например Grayscale) в TJpegImage автоматически очищает DIB-буфер. Вот пример использования такого способа: Код:
procedure TForm1.TrackBar1Change(Sender: TObject); var jpg : TJpegImage; begin ... jpg.Compress; jpg.Grayscale:=True; jpg.Grayscale:=False; // jpg.SaveToFile('D:\Out.jpg'); ImageOut.Picture.Graphic.Assign(jpg); end; Код:
procedure TForm1.TrackBar1Change(Sender: TObject); var jpg : TJpegImage; begin ... jpg.Compress; jpg.Grayscale:=not jpg.Grayscale; jpg.Grayscale:=not jpg.Grayscale; // jpg.SaveToFile('D:\Out.jpg'); ImageOut.Picture.Graphic.Assign(jpg); end; Справедливости ради отмечу ещё один способ: Код:
procedure TForm1.TrackBar1Change(Sender: TObject); var jpg : TJpegImage; ms: TMemoryStream; begin ... jpg.Compress; ms:=TMemoryStream.Create; try jpg.SaveToStream(ms); ms.Position:=0; jpg.LoadFromStream(ms); finally ms.Free; end; // jpg.SaveToFile('D:\Out.jpg'); ImageOut.Picture.Graphic.Assign(jpg); end; |
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
U.B.M. (21.08.2012)
|