Я только что проверил код TJpegImage, и гипотеза, которую я разместил в комментариях, кажется верной.
TJpegImage хранит внутреннюю TBitmap для представления. Когда вы вызываете DIBNeeded
, это растровое изображение создается на основе данных изображения Jpeg.
GetBitmap (частная функция, выполняющая работу для DIBNeeded) сначала проверит, назначено ли растровое изображение, и не будет повторять процесс, если он есть. Так что простой вызов DIBNeeded в вашем случае не сработает, так как вы гарантированно уже имеете этот кэшированный битовый массив.
Метод FreeBitmap
освободит внутреннее растровое изображение, после чего вызов DIBNeeded снова создаст новое. Поэтому я думаю, что вам нужна следующая последовательность:
Jpg.Compress; // Make sure the Jpeg compressed image data is up to date
Jpg.FreeBitmap; // Clear the internal cached bitmap
Jpg.DIBNeeded; // Optional, get a new bitmap. Will happen when you assign to TBitmap.
Я также упоминал JpegNeeded
и раньше, но это будет аналогично DIBNeeded
: проверьте, есть ли данные, если нет, позвоните Compress
. Поэтому вам нужно вызвать Compress, как и вы, чтобы вызвать это сжатие.
PS: TBitmap (и форматы файлов, аналогичные bmp), на самом деле не знает этот тип сжатия, поэтому, присвоив его обратно растровому изображению, вы уменьшите изображение качество , но не изображение размер . Некоторые форматы растровых изображений, включая PNG, сжимаются с использованием (среди прочего) кодирования длины прогона (RLE), что означает что-то вроде расходования всего четырех байтов за выражение «А теперь, 54 раза больше пикселя этого цвета!» . Этот тип сжатия не очень хорошо работает на изображениях с большим количеством артефактов в формате jpeg (зернистый / размытый побочный эффект сжатия), поэтому PNG-версия сжатого Jpg может быть больше, чем оригинальная PNG-версия, даже если качество оригинала также лучше. Это особенно верно для изображений с большими областями одного цвета, таких как снимки экрана и некоторые иллюстрации.