⬆️ Update Vampyre Imaging lib
This commit is contained in:
parent
5e47564252
commit
d30f01ac64
@ -1,28 +1,30 @@
|
||||
object frmRadarMap: TfrmRadarMap
|
||||
Left = 290
|
||||
Height = 450
|
||||
Height = 562
|
||||
Top = 171
|
||||
Width = 599
|
||||
Width = 749
|
||||
HorzScrollBar.Page = 478
|
||||
VertScrollBar.Page = 359
|
||||
ActiveControl = sbMain
|
||||
Caption = 'Radar Map (1:8)'
|
||||
ClientHeight = 450
|
||||
ClientWidth = 599
|
||||
ClientHeight = 562
|
||||
ClientWidth = 749
|
||||
DesignTimePPI = 120
|
||||
OnClose = FormClose
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
OnResize = FormResize
|
||||
Position = poOwnerFormCenter
|
||||
ShowInTaskBar = stAlways
|
||||
LCLVersion = '2.3.0.0'
|
||||
object pnlBottom: TPanel
|
||||
Left = 0
|
||||
Height = 26
|
||||
Top = 424
|
||||
Height = 32
|
||||
Top = 418
|
||||
Width = 599
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 26
|
||||
ClientHeight = 32
|
||||
ClientWidth = 599
|
||||
TabOrder = 0
|
||||
object lblPosition: TLabel
|
||||
@ -31,7 +33,7 @@ object frmRadarMap: TfrmRadarMap
|
||||
Top = 0
|
||||
Width = 1
|
||||
Align = alLeft
|
||||
BorderSpacing.Left = 10
|
||||
BorderSpacing.Left = 12
|
||||
Color = clDefault
|
||||
Layout = tlCenter
|
||||
ParentColor = False
|
||||
@ -50,9 +52,9 @@ object frmRadarMap: TfrmRadarMap
|
||||
TabOrder = 1
|
||||
object pbRadar: TPaintBox
|
||||
Left = 0
|
||||
Height = 252
|
||||
Height = 315
|
||||
Top = 0
|
||||
Width = 365
|
||||
Width = 456
|
||||
OnMouseDown = pbRadarMouseDown
|
||||
OnMouseLeave = pbRadarMouseLeave
|
||||
OnMouseMove = pbRadarMouseMove
|
||||
|
||||
@ -113,7 +113,7 @@ begin
|
||||
SetLength(radarMap, FRadar.Width * FRadar.Height);
|
||||
for x := 0 to FRadar.Width - 1 do
|
||||
for y := 0 to FRadar.Height - 1 do
|
||||
radarMap[x * FRadar.Height + y] := EncodeUOColor(PInteger(FRadar.PixelPointers[x, y])^);
|
||||
radarMap[x * FRadar.Height + y] := EncodeUOColor(PInteger(FRadar.PixelPointer[x, y])^);
|
||||
|
||||
radarMapFile := TFileStream.Create(GetAppConfigDir(False) + 'RadarMap.cache',
|
||||
fmCreate);
|
||||
@ -213,7 +213,7 @@ begin
|
||||
begin
|
||||
x := ABuffer.ReadWord;
|
||||
y := ABuffer.ReadWord;
|
||||
PInteger(FRadar.PixelPointers[x, y])^ := DecodeUOColor(ABuffer.ReadWord);
|
||||
PInteger(FRadar.PixelPointer[x, y])^ := DecodeUOColor(ABuffer.ReadWord);
|
||||
RepaintRadar;
|
||||
end;
|
||||
end;
|
||||
@ -225,7 +225,7 @@ var
|
||||
begin
|
||||
for x := 0 to FRadar.Width - 1 do
|
||||
for y := 0 to FRadar.Height - 1 do
|
||||
PInteger(FRadar.PixelPointers[x, y])^ := DecodeUOColor(ARadarMap[x * FRadar.Height + y]);
|
||||
PInteger(FRadar.PixelPointer[x, y])^ := DecodeUOColor(ARadarMap[x * FRadar.Height + y]);
|
||||
RepaintRadar;
|
||||
end;
|
||||
|
||||
|
||||
7750
Imaging/Imaging.pas
7750
Imaging/Imaging.pas
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,245 +1,230 @@
|
||||
{
|
||||
$Id: ImagingColors.pas 173 2009-09-04 17:05:52Z galfar $
|
||||
Vampyre Imaging Library
|
||||
by Marek Mauder
|
||||
http://imaginglib.sourceforge.net
|
||||
|
||||
The contents of this file are used with permission, subject to the Mozilla
|
||||
Public License Version 1.1 (the "License"); you may not use this file except
|
||||
in compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/MPL-1.1.html
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
GNU Lesser General Public License (the "LGPL License"), in which case the
|
||||
provisions of the LGPL License are applicable instead of those above.
|
||||
If you wish to allow use of your version of this file only under the terms
|
||||
of the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the LGPL License.
|
||||
|
||||
For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
|
||||
}
|
||||
|
||||
{ This unit contains functions for manipulating and converting color values.}
|
||||
unit ImagingColors;
|
||||
|
||||
interface
|
||||
|
||||
{$I ImagingOptions.inc}
|
||||
|
||||
uses
|
||||
SysUtils, ImagingTypes, ImagingUtility;
|
||||
|
||||
{ Converts RGB color to YUV.}
|
||||
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
||||
{ Converts YIV to RGB color.}
|
||||
procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte);
|
||||
|
||||
{ Converts RGB color to YCbCr as used in JPEG.}
|
||||
procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte);
|
||||
{ Converts YCbCr as used in JPEG to RGB color.}
|
||||
procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to YCbCr as used in JPEG.}
|
||||
procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word);
|
||||
{ Converts YCbCr as used in JPEG to RGB color.}
|
||||
procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to CMY.}
|
||||
procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte);
|
||||
{ Converts CMY to RGB color.}
|
||||
procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to CMY.}
|
||||
procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word);
|
||||
{ Converts CMY to RGB color.}
|
||||
procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to CMYK.}
|
||||
procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte);
|
||||
{ Converts CMYK to RGB color.}
|
||||
procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to CMYK.}
|
||||
procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||
{ Converts CMYK to RGB color.}
|
||||
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to YCoCg.}
|
||||
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||
{ Converts YCoCg to RGB color.}
|
||||
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
||||
begin
|
||||
Y := ClampToByte(Round( 0.257 * R + 0.504 * G + 0.098 * B) + 16);
|
||||
V := ClampToByte(Round( 0.439 * R - 0.368 * G - 0.071 * B) + 128);
|
||||
U := ClampToByte(Round(-0.148 * R - 0.291 * G + 0.439 * B) + 128);
|
||||
end;
|
||||
|
||||
procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte);
|
||||
var
|
||||
CY, CU, CV: LongInt;
|
||||
begin
|
||||
CY := Y - 16;
|
||||
CU := U - 128;
|
||||
CV := V - 128;
|
||||
R := ClampToByte(Round(1.164 * CY - 0.002 * CU + 1.596 * CV));
|
||||
G := ClampToByte(Round(1.164 * CY - 0.391 * CU - 0.813 * CV));
|
||||
B := ClampToByte(Round(1.164 * CY + 2.018 * CU - 0.001 * CV));
|
||||
end;
|
||||
|
||||
procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte);
|
||||
begin
|
||||
Y := ClampToByte(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B));
|
||||
Cb := ClampToByte(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 128));
|
||||
Cr := ClampToByte(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 128));
|
||||
end;
|
||||
|
||||
procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := ClampToByte(Round(Y + 1.40200 * (Cr - 128)));
|
||||
G := ClampToByte(Round(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
|
||||
B := ClampToByte(Round(Y + 1.77200 * (Cb - 128)));
|
||||
end;
|
||||
|
||||
procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word);
|
||||
begin
|
||||
Y := ClampToWord(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B));
|
||||
Cb := ClampToWord(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 32768));
|
||||
Cr := ClampToWord(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 32768));
|
||||
end;
|
||||
|
||||
procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := ClampToWord(Round(Y + 1.40200 * (Cr - 32768)));
|
||||
G := ClampToWord(Round(Y - 0.34414 * (Cb - 32768) - 0.71414 * (Cr - 32768)));
|
||||
B := ClampToWord(Round(Y + 1.77200 * (Cb - 32768)));
|
||||
end;
|
||||
|
||||
procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte);
|
||||
begin
|
||||
C := 255 - R;
|
||||
M := 255 - G;
|
||||
Y := 255 - B;
|
||||
end;
|
||||
|
||||
procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := 255 - C;
|
||||
G := 255 - M;
|
||||
B := 255 - Y;
|
||||
end;
|
||||
|
||||
procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word);
|
||||
begin
|
||||
C := 65535 - R;
|
||||
M := 65535 - G;
|
||||
Y := 65535 - B;
|
||||
end;
|
||||
|
||||
procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := 65535 - C;
|
||||
G := 65535 - M;
|
||||
B := 65535 - Y;
|
||||
end;
|
||||
|
||||
procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte);
|
||||
begin
|
||||
RGBToCMY(R, G, B, C, M, Y);
|
||||
K := Min(C, Min(M, Y));
|
||||
if K = 255 then
|
||||
begin
|
||||
C := 0;
|
||||
M := 0;
|
||||
Y := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
C := ClampToByte(Round((C - K) / (255 - K) * 255));
|
||||
M := ClampToByte(Round((M - K) / (255 - K) * 255));
|
||||
Y := ClampToByte(Round((Y - K) / (255 - K) * 255));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := (255 - (C - MulDiv(C, K, 255) + K));
|
||||
G := (255 - (M - MulDiv(M, K, 255) + K));
|
||||
B := (255 - (Y - MulDiv(Y, K, 255) + K));
|
||||
end;
|
||||
|
||||
procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||
begin
|
||||
RGBToCMY16(R, G, B, C, M, Y);
|
||||
K := Min(C, Min(M, Y));
|
||||
if K = 65535 then
|
||||
begin
|
||||
C := 0;
|
||||
M := 0;
|
||||
Y := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
C := ClampToWord(Round((C - K) / (65535 - K) * 65535));
|
||||
M := ClampToWord(Round((M - K) / (65535 - K) * 65535));
|
||||
Y := ClampToWord(Round((Y - K) / (65535 - K) * 65535));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := 65535 - (C - MulDiv(C, K, 65535) + K);
|
||||
G := 65535 - (M - MulDiv(M, K, 65535) + K);
|
||||
B := 65535 - (Y - MulDiv(Y, K, 65535) + K);
|
||||
end;
|
||||
|
||||
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||
begin
|
||||
// C and Delphi's SHR behaviour differs for negative numbers, use div instead.
|
||||
Y := ClampToByte(( R + G shl 1 + B + 2) div 4);
|
||||
Co := ClampToByte(( R shl 1 - B shl 1 + 2) div 4 + 128);
|
||||
Cg := ClampToByte((-R + G shl 1 - B + 2) div 4 + 128);
|
||||
end;
|
||||
|
||||
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||
var
|
||||
CoInt, CgInt: Integer;
|
||||
begin
|
||||
CoInt := Co - 128;
|
||||
CgInt := Cg - 128;
|
||||
R := ClampToByte(Y + CoInt - CgInt);
|
||||
G := ClampToByte(Y + CgInt);
|
||||
B := ClampToByte(Y - CoInt - CgInt);
|
||||
end;
|
||||
|
||||
{
|
||||
File Notes:
|
||||
|
||||
-- TODOS ----------------------------------------------------
|
||||
- nothing now
|
||||
|
||||
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||
- Added RGB<>YCoCg conversion functions.
|
||||
- Fixed RGB>>CMYK conversions.
|
||||
|
||||
-- 0.23 Changes/Bug Fixes -----------------------------------
|
||||
- Added RGB<>CMY(K) converion functions for 16 bit channels
|
||||
(needed by PSD loading code).
|
||||
|
||||
-- 0.21 Changes/Bug Fixes -----------------------------------
|
||||
- Added some color space conversion functions and LUTs
|
||||
(RGB/YUV/YCrCb/CMY/CMYK).
|
||||
|
||||
-- 0.17 Changes/Bug Fixes -----------------------------------
|
||||
- unit created (empty!)
|
||||
}
|
||||
|
||||
end.
|
||||
{
|
||||
Vampyre Imaging Library
|
||||
by Marek Mauder
|
||||
https://github.com/galfar/imaginglib
|
||||
https://imaginglib.sourceforge.io
|
||||
- - - - -
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0.
|
||||
}
|
||||
|
||||
{ This unit contains functions for manipulating and converting color values.}
|
||||
unit ImagingColors;
|
||||
|
||||
interface
|
||||
|
||||
{$I ImagingOptions.inc}
|
||||
|
||||
uses
|
||||
SysUtils, ImagingTypes, ImagingUtility;
|
||||
|
||||
{ Converts RGB color to YUV.}
|
||||
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
||||
{ Converts YIV to RGB color.}
|
||||
procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte);
|
||||
|
||||
{ Converts RGB color to YCbCr as used in JPEG.}
|
||||
procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte);
|
||||
{ Converts YCbCr as used in JPEG to RGB color.}
|
||||
procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to YCbCr as used in JPEG.}
|
||||
procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word);
|
||||
{ Converts YCbCr as used in JPEG to RGB color.}
|
||||
procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to CMY.}
|
||||
procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte);
|
||||
{ Converts CMY to RGB color.}
|
||||
procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to CMY.}
|
||||
procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word);
|
||||
{ Converts CMY to RGB color.}
|
||||
procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to CMYK.}
|
||||
procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte);
|
||||
{ Converts CMYK to RGB color.}
|
||||
procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte);
|
||||
{ Converts RGB color to CMYK.}
|
||||
procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||
{ Converts CMYK to RGB color.}
|
||||
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
||||
|
||||
{ Converts RGB color to YCoCg.}
|
||||
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||
{ Converts YCoCg to RGB color.}
|
||||
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||
|
||||
//procedure RGBToHSL(R, G, B: Byte; var H, S, L: Byte);
|
||||
//procedure HSLToRGB(H, S, L: Byte; var R, G, B: Byte);
|
||||
|
||||
implementation
|
||||
|
||||
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
||||
begin
|
||||
Y := ClampToByte(Round( 0.257 * R + 0.504 * G + 0.098 * B) + 16);
|
||||
V := ClampToByte(Round( 0.439 * R - 0.368 * G - 0.071 * B) + 128);
|
||||
U := ClampToByte(Round(-0.148 * R - 0.291 * G + 0.439 * B) + 128);
|
||||
end;
|
||||
|
||||
procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte);
|
||||
var
|
||||
CY, CU, CV: LongInt;
|
||||
begin
|
||||
CY := Y - 16;
|
||||
CU := U - 128;
|
||||
CV := V - 128;
|
||||
R := ClampToByte(Round(1.164 * CY - 0.002 * CU + 1.596 * CV));
|
||||
G := ClampToByte(Round(1.164 * CY - 0.391 * CU - 0.813 * CV));
|
||||
B := ClampToByte(Round(1.164 * CY + 2.018 * CU - 0.001 * CV));
|
||||
end;
|
||||
|
||||
procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte);
|
||||
begin
|
||||
Y := ClampToByte(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B));
|
||||
Cb := ClampToByte(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 128));
|
||||
Cr := ClampToByte(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 128));
|
||||
end;
|
||||
|
||||
procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := ClampToByte(Round(Y + 1.40200 * (Cr - 128)));
|
||||
G := ClampToByte(Round(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
|
||||
B := ClampToByte(Round(Y + 1.77200 * (Cb - 128)));
|
||||
end;
|
||||
|
||||
procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word);
|
||||
begin
|
||||
Y := ClampToWord(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B));
|
||||
Cb := ClampToWord(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 32768));
|
||||
Cr := ClampToWord(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 32768));
|
||||
end;
|
||||
|
||||
procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := ClampToWord(Round(Y + 1.40200 * (Cr - 32768)));
|
||||
G := ClampToWord(Round(Y - 0.34414 * (Cb - 32768) - 0.71414 * (Cr - 32768)));
|
||||
B := ClampToWord(Round(Y + 1.77200 * (Cb - 32768)));
|
||||
end;
|
||||
|
||||
procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte);
|
||||
begin
|
||||
C := 255 - R;
|
||||
M := 255 - G;
|
||||
Y := 255 - B;
|
||||
end;
|
||||
|
||||
procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := 255 - C;
|
||||
G := 255 - M;
|
||||
B := 255 - Y;
|
||||
end;
|
||||
|
||||
procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word);
|
||||
begin
|
||||
C := 65535 - R;
|
||||
M := 65535 - G;
|
||||
Y := 65535 - B;
|
||||
end;
|
||||
|
||||
procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := 65535 - C;
|
||||
G := 65535 - M;
|
||||
B := 65535 - Y;
|
||||
end;
|
||||
|
||||
procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte);
|
||||
begin
|
||||
RGBToCMY(R, G, B, C, M, Y);
|
||||
K := Min(C, Min(M, Y));
|
||||
if K = 255 then
|
||||
begin
|
||||
C := 0;
|
||||
M := 0;
|
||||
Y := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
C := ClampToByte(Round((C - K) / (255 - K) * 255));
|
||||
M := ClampToByte(Round((M - K) / (255 - K) * 255));
|
||||
Y := ClampToByte(Round((Y - K) / (255 - K) * 255));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte);
|
||||
begin
|
||||
R := (255 - (C - MulDiv(C, K, 255) + K));
|
||||
G := (255 - (M - MulDiv(M, K, 255) + K));
|
||||
B := (255 - (Y - MulDiv(Y, K, 255) + K));
|
||||
end;
|
||||
|
||||
procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||
begin
|
||||
RGBToCMY16(R, G, B, C, M, Y);
|
||||
K := Min(C, Min(M, Y));
|
||||
if K = 65535 then
|
||||
begin
|
||||
C := 0;
|
||||
M := 0;
|
||||
Y := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
C := ClampToWord(Round((C - K) / (65535 - K) * 65535));
|
||||
M := ClampToWord(Round((M - K) / (65535 - K) * 65535));
|
||||
Y := ClampToWord(Round((Y - K) / (65535 - K) * 65535));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
||||
begin
|
||||
R := 65535 - (C - MulDiv(C, K, 65535) + K);
|
||||
G := 65535 - (M - MulDiv(M, K, 65535) + K);
|
||||
B := 65535 - (Y - MulDiv(Y, K, 65535) + K);
|
||||
end;
|
||||
|
||||
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||
begin
|
||||
// C and Delphi's SHR behaviour differs for negative numbers, use div instead.
|
||||
Y := ClampToByte(( R + G shl 1 + B + 2) div 4);
|
||||
Co := ClampToByte(( R shl 1 - B shl 1 + 2) div 4 + 128);
|
||||
Cg := ClampToByte((-R + G shl 1 - B + 2) div 4 + 128);
|
||||
end;
|
||||
|
||||
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||
var
|
||||
CoInt, CgInt: Integer;
|
||||
begin
|
||||
CoInt := Co - 128;
|
||||
CgInt := Cg - 128;
|
||||
R := ClampToByte(Y + CoInt - CgInt);
|
||||
G := ClampToByte(Y + CgInt);
|
||||
B := ClampToByte(Y - CoInt - CgInt);
|
||||
end;
|
||||
|
||||
{
|
||||
File Notes:
|
||||
|
||||
-- TODOS ----------------------------------------------------
|
||||
- nothing now
|
||||
|
||||
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||
- Added RGB<>YCoCg conversion functions.
|
||||
- Fixed RGB>>CMYK conversions.
|
||||
|
||||
-- 0.23 Changes/Bug Fixes -----------------------------------
|
||||
- Added RGB<>CMY(K) conversion functions for 16 bit channels
|
||||
(needed by PSD loading code).
|
||||
|
||||
-- 0.21 Changes/Bug Fixes -----------------------------------
|
||||
- Added some color space conversion functions and LUTs
|
||||
(RGB/YUV/YCrCb/CMY/CMYK).
|
||||
|
||||
-- 0.17 Changes/Bug Fixes -----------------------------------
|
||||
- unit created (empty!)
|
||||
}
|
||||
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,891 +0,0 @@
|
||||
{
|
||||
$Id: ImagingExport.pas 173 2009-09-04 17:05:52Z galfar $
|
||||
Vampyre Imaging Library
|
||||
by Marek Mauder
|
||||
http://imaginglib.sourceforge.net
|
||||
|
||||
The contents of this file are used with permission, subject to the Mozilla
|
||||
Public License Version 1.1 (the "License"); you may not use this file except
|
||||
in compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/MPL-1.1.html
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
GNU Lesser General Public License (the "LGPL License"), in which case the
|
||||
provisions of the LGPL License are applicable instead of those above.
|
||||
If you wish to allow use of your version of this file only under the terms
|
||||
of the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use
|
||||
your version of this file under either the MPL or the LGPL License.
|
||||
|
||||
For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
|
||||
}
|
||||
|
||||
{ This function contains functions exported from Imaging dynamic link library.
|
||||
All string are exported as PChars and all var parameters are exported
|
||||
as pointers. All posible exceptions getting out of dll are catched.}
|
||||
unit ImagingExport;
|
||||
|
||||
{$I ImagingOptions.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ImagingTypes,
|
||||
Imaging;
|
||||
|
||||
{ Returns version of Imaging library. }
|
||||
procedure ImGetVersion(var Major, Minor, Patch: LongInt); cdecl;
|
||||
{ Look at InitImage for details.}
|
||||
procedure ImInitImage(var Image: TImageData); cdecl;
|
||||
{ Look at NewImage for details.}
|
||||
function ImNewImage(Width, Height: LongInt; Format: TImageFormat;
|
||||
var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at TestImage for details.}
|
||||
function ImTestImage(var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at FreeImage for details.}
|
||||
function ImFreeImage(var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at DetermineFileFormat for details. Ext should have enough space for
|
||||
result file extension.}
|
||||
function ImDetermineFileFormat(FileName, Ext: PAnsiChar): Boolean; cdecl;
|
||||
{ Look at DetermineMemoryFormat for details. Ext should have enough space for
|
||||
result file extension.}
|
||||
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PAnsiChar): Boolean; cdecl;
|
||||
{ Look at IsFileFormatSupported for details.}
|
||||
function ImIsFileFormatSupported(FileName: PAnsiChar): Boolean; cdecl;
|
||||
{ Look at EnumFileFormats for details.}
|
||||
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PAnsiChar;
|
||||
var CanSave, IsMultiImageFormat: Boolean): Boolean; cdecl;
|
||||
|
||||
{ Inits image list.}
|
||||
function ImInitImageList(Size: LongInt; var ImageList: TImageDataList): Boolean; cdecl;
|
||||
{ Returns size of image list.}
|
||||
function ImGetImageListSize(ImageList: TImageDataList): LongInt; cdecl;
|
||||
{ Returns image list's element at given index. Output image is not cloned it's
|
||||
Bits point to Bits in list => do not free OutImage.}
|
||||
function ImGetImageListElement(ImageList: TImageDataList; Index: LongInt;
|
||||
var OutImage: TImageData): Boolean; cdecl;
|
||||
{ Sets size of image list.}
|
||||
function ImSetImageListSize(ImageList: TImageDataList; NewSize: LongInt): Boolean; cdecl;
|
||||
{ Sets image list element at given index. Input image is not cloned - image in
|
||||
list will point to InImage's Bits.}
|
||||
function ImSetImageListElement(ImageList: TImageDataList; Index: LongInt;
|
||||
const InImage: TImageData): Boolean; cdecl;
|
||||
{ Returns True if all images in list pass ImTestImage test. }
|
||||
function ImTestImagesInList(ImageList: TImageDataList): Boolean; cdecl;
|
||||
{ Frees image list and all images in it.}
|
||||
function ImFreeImageList(var ImageList: TImageDataList): Boolean; cdecl;
|
||||
|
||||
{ Look at LoadImageFromFile for details.}
|
||||
function ImLoadImageFromFile(FileName: PAnsiChar; var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at LoadImageFromMemory for details.}
|
||||
function ImLoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at LoadMultiImageFromFile for details.}
|
||||
function ImLoadMultiImageFromFile(FileName: PAnsiChar; var ImageList: TImageDataList): Boolean; cdecl;
|
||||
{ Look at LoadMultiImageFromMemory for details.}
|
||||
function ImLoadMultiImageFromMemory(Data: Pointer; Size: LongInt;
|
||||
var ImageList: TImageDataList): Boolean; cdecl;
|
||||
|
||||
{ Look at SaveImageToFile for details.}
|
||||
function ImSaveImageToFile(FileName: PAnsiChar; const Image: TImageData): Boolean; cdecl;
|
||||
{ Look at SaveImageToMemory for details.}
|
||||
function ImSaveImageToMemory(Ext: PAnsiChar; Data: Pointer; var Size: LongInt;
|
||||
const Image: TImageData): Boolean; cdecl;
|
||||
{ Look at SaveMultiImageToFile for details.}
|
||||
function ImSaveMultiImageToFile(FileName: PAnsiChar; ImageList: TImageDataList): Boolean; cdecl;
|
||||
{ Look at SaveMultiImageToMemory for details.}
|
||||
function ImSaveMultiImageToMemory(Ext: PAnsiChar; Data: Pointer; Size: PLongInt;
|
||||
ImageList: TImageDataList): Boolean; cdecl;
|
||||
|
||||
{ Look at CloneImage for details.}
|
||||
function ImCloneImage(const Image: TImageData; var Clone: TImageData): Boolean; cdecl;
|
||||
{ Look at ConvertImage for details.}
|
||||
function ImConvertImage(var Image: TImageData; DestFormat: TImageFormat): Boolean; cdecl;
|
||||
{ Look at FlipImage for details.}
|
||||
function ImFlipImage(var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at MirrorImage for details.}
|
||||
function ImMirrorImage(var Image: TImageData): Boolean; cdecl;
|
||||
{ Look at ResizeImage for details.}
|
||||
function ImResizeImage(var Image: TImageData; NewWidth, NewHeight: LongInt;
|
||||
Filter: TResizeFilter): Boolean; cdecl;
|
||||
{ Look at SwapChannels for details.}
|
||||
function ImSwapChannels(var Image: TImageData; SrcChannel, DstChannel: LongInt): Boolean; cdecl;
|
||||
{ Look at ReduceColors for details.}
|
||||
function ImReduceColors(var Image: TImageData; MaxColors: LongInt): Boolean; cdecl;
|
||||
{ Look at GenerateMipMaps for details.}
|
||||
function ImGenerateMipMaps(const Image: TImageData; Levels: LongInt;
|
||||
var MipMaps: TImageDataList): Boolean; cdecl;
|
||||
{ Look at MapImageToPalette for details.}
|
||||
function ImMapImageToPalette(var Image: TImageData; Pal: PPalette32;
|
||||
Entries: LongInt): Boolean; cdecl;
|
||||
{ Look at SplitImage for details.}
|
||||
function ImSplitImage(var Image: TImageData; var Chunks: TImageDataList;
|
||||
ChunkWidth, ChunkHeight: LongInt; var XChunks, YChunks: LongInt;
|
||||
PreserveSize: Boolean; Fill: Pointer): Boolean; cdecl;
|
||||
{ Look at MakePaletteForImages for details.}
|
||||
function ImMakePaletteForImages(Images: TImageDataList; Pal: PPalette32;
|
||||
MaxColors: LongInt; ConvertImages: Boolean): Boolean; cdecl;
|
||||
{ Look at RotateImage for details.}
|
||||
function ImRotateImage(var Image: TImageData; Angle: Single): Boolean; cdecl;
|
||||
|
||||
{ Look at CopyRect for details.}
|
||||
function ImCopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt;
|
||||
var DstImage: TImageData; DstX, DstY: LongInt): Boolean; cdecl;
|
||||
{ Look at FillRect for details.}
|
||||
function ImFillRect(var Image: TImageData; X, Y, Width, Height: LongInt;
|
||||
Fill: Pointer): Boolean; cdecl;
|
||||
{ Look at ReplaceColor for details.}
|
||||
function ImReplaceColor(var Image: TImageData; X, Y, Width, Height: LongInt;
|
||||
OldPixel, NewPixel: Pointer): Boolean; cdecl;
|
||||
{ Look at StretchRect for details.}
|
||||
function ImStretchRect(const SrcImage: TImageData; SrcX, SrcY, SrcWidth,
|
||||
SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth,
|
||||
DstHeight: LongInt; Filter: TResizeFilter): Boolean; cdecl;
|
||||
{ Look at GetPixelDirect for details.}
|
||||
procedure ImGetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); cdecl;
|
||||
{ Look at SetPixelDirect for details.}
|
||||
procedure ImSetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); cdecl;
|
||||
{ Look at GetPixel32 for details.}
|
||||
function ImGetPixel32(const Image: TImageData; X, Y: LongInt): TColor32Rec; cdecl;
|
||||
{ Look at SetPixel32 for details.}
|
||||
procedure ImSetPixel32(const Image: TImageData; X, Y: LongInt; const Color: TColor32Rec); cdecl;
|
||||
{ Look at GetPixelFP for details.}
|
||||
function ImGetPixelFP(const Image: TImageData; X, Y: LongInt): TColorFPRec; cdecl;
|
||||
{ Look at SetPixelFP for details.}
|
||||
procedure ImSetPixelFP(const Image: TImageData; X, Y: LongInt; const Color: TColorFPRec); cdecl;
|
||||
|
||||
{ Look at NewPalette for details.}
|
||||
function ImNewPalette(Entries: LongInt; var Pal: PPalette32): Boolean; cdecl;
|
||||
{ Look at FreePalette for details.}
|
||||
function ImFreePalette(var Pal: PPalette32): Boolean; cdecl;
|
||||
{ Look at CopyPalette for details.}
|
||||
function ImCopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt): Boolean; cdecl;
|
||||
{ Look at FindColor for details.}
|
||||
function ImFindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): LongInt; cdecl;
|
||||
{ Look at FillGrayscalePalette for details.}
|
||||
function ImFillGrayscalePalette(Pal: PPalette32; Entries: LongInt): Boolean; cdecl;
|
||||
{ Look at FillCustomPalette for details.}
|
||||
function ImFillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits,
|
||||
BBits: Byte; Alpha: Byte): Boolean; cdecl;
|
||||
{ Look at SwapChannelsOfPalette for details.}
|
||||
function ImSwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel,
|
||||
DstChannel: LongInt): Boolean; cdecl;
|
||||
|
||||
{ Look at SetOption for details.}
|
||||
function ImSetOption(OptionId, Value: LongInt): Boolean; cdecl;
|
||||
{ Look at GetOption for details.}
|
||||
function ImGetOption(OptionId: LongInt): LongInt; cdecl;
|
||||
{ Look at PushOptions for details.}
|
||||
function ImPushOptions: Boolean; cdecl;
|
||||
{ Look at PopOptions for details.}
|
||||
function ImPopOptions: Boolean; cdecl;
|
||||
|
||||
{ Look at GetImageFormatInfo for details.}
|
||||
function ImGetImageFormatInfo(Format: TImageFormat; var Info: TImageFormatInfo): Boolean; cdecl;
|
||||
{ Look at GetPixelsSize for details.}
|
||||
function ImGetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; cdecl;
|
||||
|
||||
{ Look at SetUserFileIO for details.}
|
||||
procedure ImSetUserFileIO(OpenReadProc: TOpenReadProc; OpenWriteProc:
|
||||
TOpenWriteProc; CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: TSeekProc;
|
||||
TellProc: TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc); cdecl;
|
||||
{ Look at ResetFileIO for details.}
|
||||
procedure ImResetFileIO; cdecl;
|
||||
|
||||
{ These are only for documentation generation reasons.}
|
||||
{ Loads Imaging functions from dll/so library.}
|
||||
function ImLoadLibrary: Boolean;
|
||||
{ Frees Imaging functions loaded from dll/so and releases library.}
|
||||
function ImFreeLibrary: Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
ImagingUtility;
|
||||
|
||||
function ImLoadLibrary: Boolean; begin Result := True; end;
|
||||
function ImFreeLibrary: Boolean; begin Result := True; end;
|
||||
|
||||
type
|
||||
TInternalList = record
|
||||
List: TDynImageDataArray;
|
||||
end;
|
||||
PInternalList = ^TInternalList;
|
||||
|
||||
procedure ImGetVersion(var Major, Minor, Patch: LongInt);
|
||||
begin
|
||||
Major := ImagingVersionMajor;
|
||||
Minor := ImagingVersionMinor;
|
||||
Patch := ImagingVersionPatch;
|
||||
end;
|
||||
|
||||
procedure ImInitImage(var Image: TImageData);
|
||||
begin
|
||||
try
|
||||
Imaging.InitImage(Image);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImNewImage(Width, Height: LongInt; Format: TImageFormat;
|
||||
var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.NewImage(Width, Height, Format, Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImTestImage(var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.TestImage(Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFreeImage(var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.FreeImage(Image);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImDetermineFileFormat(FileName, Ext: PAnsiChar): Boolean;
|
||||
var
|
||||
S: string;
|
||||
begin
|
||||
try
|
||||
S := Imaging.DetermineFileFormat(FileName);
|
||||
Result := S <> '';
|
||||
StrCopy(Ext, PAnsiChar(AnsiString(S)));
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PAnsiChar): Boolean;
|
||||
var
|
||||
S: string;
|
||||
begin
|
||||
try
|
||||
S := Imaging.DetermineMemoryFormat(Data, Size);
|
||||
Result := S <> '';
|
||||
StrCopy(Ext, PAnsiChar(AnsiString(S)));
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImIsFileFormatSupported(FileName: PAnsiChar): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.IsFileFormatSupported(FileName);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PAnsiChar;
|
||||
var CanSave, IsMultiImageFormat: Boolean): Boolean;
|
||||
var
|
||||
StrName, StrDefaultExt, StrMasks: string;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.EnumFileFormats(Index, StrName, StrDefaultExt, StrMasks, CanSave,
|
||||
IsMultiImageFormat);
|
||||
StrCopy(Name, PAnsiChar(AnsiString(StrName)));
|
||||
StrCopy(DefaultExt, PAnsiChar(AnsiString(StrDefaultExt)));
|
||||
StrCopy(Masks, PAnsiChar(AnsiString(StrMasks)));
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImInitImageList(Size: LongInt; var ImageList: TImageDataList): Boolean;
|
||||
var
|
||||
Int: PInternalList;
|
||||
begin
|
||||
try
|
||||
try
|
||||
ImFreeImageList(ImageList);
|
||||
except
|
||||
end;
|
||||
New(Int);
|
||||
SetLength(Int.List, Size);
|
||||
ImageList := TImageDataList(Int);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
ImageList := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetImageListSize(ImageList: TImageDataList): LongInt;
|
||||
begin
|
||||
try
|
||||
Result := Length(PInternalList(ImageList).List);
|
||||
except
|
||||
Result := -1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetImageListElement(ImageList: TImageDataList; Index: LongInt;
|
||||
var OutImage: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Index := ClampInt(Index, 0, Length(PInternalList(ImageList).List) - 1);
|
||||
ImCloneImage(PInternalList(ImageList).List[Index], OutImage);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSetImageListSize(ImageList: TImageDataList; NewSize: LongInt):
|
||||
Boolean;
|
||||
var
|
||||
I, OldSize: LongInt;
|
||||
begin
|
||||
try
|
||||
OldSize := Length(PInternalList(ImageList).List);
|
||||
if NewSize < OldSize then
|
||||
for I := NewSize to OldSize - 1 do
|
||||
Imaging.FreeImage(PInternalList(ImageList).List[I]);
|
||||
SetLength(PInternalList(ImageList).List, NewSize);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSetImageListElement(ImageList: TImageDataList; Index: LongInt;
|
||||
const InImage: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Index := ClampInt(Index, 0, Length(PInternalList(ImageList).List) - 1);
|
||||
ImCloneImage(InImage, PInternalList(ImageList).List[Index]);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImTestImagesInList(ImageList: TImageDataList): Boolean;
|
||||
var
|
||||
I: LongInt;
|
||||
Arr: TDynImageDataArray;
|
||||
begin
|
||||
Arr := nil;
|
||||
try
|
||||
Arr := PInternalList(ImageList).List;
|
||||
Result := True;
|
||||
for I := 0 to Length(Arr) - 1 do
|
||||
begin
|
||||
Result := Result and Imaging.TestImage(Arr[I]);
|
||||
if not Result then Break;
|
||||
end;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFreeImageList(var ImageList: TImageDataList): Boolean;
|
||||
var
|
||||
Int: PInternalList;
|
||||
begin
|
||||
try
|
||||
if ImageList <> nil then
|
||||
begin
|
||||
Int := PInternalList(ImageList);
|
||||
FreeImagesInArray(Int.List);
|
||||
Dispose(Int);
|
||||
ImageList := nil;
|
||||
end;
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImLoadImageFromFile(FileName: PAnsiChar; var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.LoadImageFromFile(FileName, Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImLoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.LoadImageFromMemory(Data, Size, Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImLoadMultiImageFromFile(FileName: PAnsiChar; var ImageList: TImageDataList):
|
||||
Boolean;
|
||||
begin
|
||||
try
|
||||
ImInitImageList(0, ImageList);
|
||||
Result := Imaging.LoadMultiImageFromFile(FileName,
|
||||
PInternalList(ImageList).List);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImLoadMultiImageFromMemory(Data: Pointer; Size: LongInt;
|
||||
var ImageList: TImageDataList): Boolean;
|
||||
begin
|
||||
try
|
||||
ImInitImageList(0, ImageList);
|
||||
Result := Imaging.LoadMultiImageFromMemory(Data, Size, PInternalList(ImageList).List);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSaveImageToFile(FileName: PAnsiChar; const Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SaveImageToFile(FileName, Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSaveImageToMemory(Ext: PAnsiChar; Data: Pointer; var Size: LongInt;
|
||||
const Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SaveImageToMemory(Ext, Data, Size, Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSaveMultiImageToFile(FileName: PAnsiChar;
|
||||
ImageList: TImageDataList): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SaveMultiImageToFile(FileName,
|
||||
PInternalList(ImageList).List);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSaveMultiImageToMemory(Ext: PAnsiChar; Data: Pointer; Size: PLongInt;
|
||||
ImageList: TImageDataList): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SaveMultiImageToMemory(Ext, Data, Size^,
|
||||
PInternalList(ImageList).List);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImCloneImage(const Image: TImageData; var Clone: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.CloneImage(Image, Clone);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImConvertImage(var Image: TImageData; DestFormat: TImageFormat): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.ConvertImage(Image, DestFormat);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFlipImage(var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.FlipImage(Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImMirrorImage(var Image: TImageData): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.MirrorImage(Image);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImResizeImage(var Image: TImageData; NewWidth, NewHeight: LongInt;
|
||||
Filter: TResizeFilter): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.ResizeImage(Image, NewWidth, NewHeight, Filter);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSwapChannels(var Image: TImageData; SrcChannel, DstChannel: LongInt):
|
||||
Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SwapChannels(Image, SrcChannel, DstChannel);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImReduceColors(var Image: TImageData; MaxColors: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.ReduceColors(Image, MaxColors);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGenerateMipMaps(const Image: TImageData; Levels: LongInt;
|
||||
var MipMaps: TImageDataList): Boolean;
|
||||
begin
|
||||
try
|
||||
ImInitImageList(0, MipMaps);
|
||||
Result := Imaging.GenerateMipMaps(Image, Levels,
|
||||
PInternalList(MipMaps).List);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImMapImageToPalette(var Image: TImageData; Pal: PPalette32;
|
||||
Entries: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.MapImageToPalette(Image, Pal, Entries);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSplitImage(var Image: TImageData; var Chunks: TImageDataList;
|
||||
ChunkWidth, ChunkHeight: LongInt; var XChunks, YChunks: LongInt;
|
||||
PreserveSize: Boolean; Fill: Pointer): Boolean;
|
||||
begin
|
||||
try
|
||||
ImInitImageList(0, Chunks);
|
||||
Result := Imaging.SplitImage(Image, PInternalList(Chunks).List,
|
||||
ChunkWidth, ChunkHeight, XChunks, YChunks, PreserveSize, Fill);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImMakePaletteForImages(Images: TImageDataList; Pal: PPalette32;
|
||||
MaxColors: LongInt; ConvertImages: Boolean): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.MakePaletteForImages(PInternalList(Images).List,
|
||||
Pal, MaxColors, ConvertImages);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImRotateImage(var Image: TImageData; Angle: Single): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.RotateImage(Image, Angle);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImCopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt;
|
||||
var DstImage: TImageData; DstX, DstY: LongInt): Boolean; cdecl;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.CopyRect(SrcImage, SrcX, SrcY, Width, Height,
|
||||
DstImage, DstX, DstY);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFillRect(var Image: TImageData; X, Y, Width, Height: LongInt;
|
||||
Fill: Pointer): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.FillRect(Image, X, Y, Width, Height, Fill);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImReplaceColor(var Image: TImageData; X, Y, Width, Height: LongInt;
|
||||
OldPixel, NewPixel: Pointer): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.ReplaceColor(Image, X, Y, Width, Height, OldPixel, NewPixel);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImStretchRect(const SrcImage: TImageData; SrcX, SrcY, SrcWidth,
|
||||
SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth,
|
||||
DstHeight: LongInt; Filter: TResizeFilter): Boolean; cdecl;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.StretchRect(SrcImage, SrcX, SrcY, SrcWidth, SrcHeight,
|
||||
DstImage, DstX, DstY, DstWidth, DstHeight, Filter);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImGetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer);
|
||||
begin
|
||||
try
|
||||
Imaging.GetPixelDirect(Image, X, Y, Pixel);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImSetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer);
|
||||
begin
|
||||
try
|
||||
Imaging.SetPixelDirect(Image, X, Y, Pixel);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetPixel32(const Image: TImageData; X, Y: LongInt): TColor32Rec; cdecl;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.GetPixel32(Image, X, Y);
|
||||
except
|
||||
Result.Color := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImSetPixel32(const Image: TImageData; X, Y: LongInt; const Color: TColor32Rec);
|
||||
begin
|
||||
try
|
||||
Imaging.SetPixel32(Image, X, Y, Color);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetPixelFP(const Image: TImageData; X, Y: LongInt): TColorFPRec; cdecl;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.GetPixelFP(Image, X, Y);
|
||||
except
|
||||
FillChar(Result, SizeOf(Result), 0);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImSetPixelFP(const Image: TImageData; X, Y: LongInt; const Color: TColorFPRec);
|
||||
begin
|
||||
try
|
||||
Imaging.SetPixelFP(Image, X, Y, Color);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImNewPalette(Entries: LongInt; var Pal: PPalette32): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.NewPalette(Entries, Pal);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFreePalette(var Pal: PPalette32): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.FreePalette(Pal);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImCopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.CopyPalette(SrcPal, DstPal, SrcIdx, DstIdx, Count);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): LongInt;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.FindColor(Pal, Entries, Color);
|
||||
except
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFillGrayscalePalette(Pal: PPalette32; Entries: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.FillGrayscalePalette(Pal, Entries);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImFillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits,
|
||||
BBits: Byte; Alpha: Byte): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.FillCustomPalette(Pal, Entries, RBits, GBits, BBits, Alpha);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel,
|
||||
DstChannel: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Imaging.SwapChannelsOfPalette(Pal, Entries, SrcChannel, DstChannel);
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImSetOption(OptionId, Value: LongInt): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.SetOption(OptionId, Value);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetOption(OptionId: LongInt): LongInt;
|
||||
begin
|
||||
try
|
||||
Result := GetOption(OptionId);
|
||||
except
|
||||
Result := InvalidOption;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImPushOptions: Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.PushOptions;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImPopOptions: Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.PopOptions;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetImageFormatInfo(Format: TImageFormat; var Info: TImageFormatInfo): Boolean;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.GetImageFormatInfo(Format, Info);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ImGetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt;
|
||||
begin
|
||||
try
|
||||
Result := Imaging.GetPixelsSize(Format, Width, Height);
|
||||
except
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImSetUserFileIO(OpenReadProc: TOpenReadProc; OpenWriteProc:
|
||||
TOpenWriteProc; CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: TSeekProc;
|
||||
TellProc: TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc);
|
||||
begin
|
||||
try
|
||||
Imaging.SetUserFileIO(OpenReadProc, OpenWriteProc, CloseProc, EofProc,
|
||||
SeekProc, TellProc, ReadProc, WriteProc);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ImResetFileIO;
|
||||
begin
|
||||
try
|
||||
Imaging.ResetFileIO;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
Changes/Bug Fixes:
|
||||
|
||||
-- TODOS ----------------------------------------------------
|
||||
- nothing now
|
||||
|
||||
-- 0.26.3 ---------------------------------------------------
|
||||
- changed PChars to PAnsiChars and some more D2009 friendly
|
||||
casts.
|
||||
|
||||
-- 0.19 -----------------------------------------------------
|
||||
- updated to reflect changes in low level interface (added pixel set/get, ...)
|
||||
- changed ImInitImage to procedure to reflect change in Imaging.pas
|
||||
- added ImIsFileFormatSupported
|
||||
|
||||
-- 0.15 -----------------------------------------------------
|
||||
- behaviour of ImGetImageListElement and ImSetImageListElement
|
||||
has changed - list items are now cloned rather than referenced,
|
||||
because of this ImFreeImageListKeepImages was no longer needed
|
||||
and was removed
|
||||
- many function headers were changed - mainly pointers were
|
||||
replaced with var and const parameters
|
||||
|
||||
-- 0.13 -----------------------------------------------------
|
||||
- added TestImagesInList function and new 0.13 functions
|
||||
- images were not freed when image list was resized in ImSetImageListSize
|
||||
- ImSaveMultiImageTo* recreated the input image list with size = 0
|
||||
|
||||
}
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,188 +1,228 @@
|
||||
{ $Id: ImagingOptions.inc 174 2009-09-08 09:37:59Z galfar $ }
|
||||
|
||||
{
|
||||
User Options
|
||||
Following defines and options can be changed by user.
|
||||
}
|
||||
|
||||
{ Source options }
|
||||
|
||||
{$DEFINE USE_INLINE} // Use function inlining for some functions
|
||||
// works in Free Pascal and Delphi 9+.
|
||||
{.$DEFINE USE_ASM} // Ff defined, assembler versions of some
|
||||
// functions will be used (only for x86).
|
||||
|
||||
// Debug options: If none of these two are defined
|
||||
// your project settings are used.
|
||||
{ $DEFINE IMAGING_DEBUG} // If defined, debug info, range/IO/overflow
|
||||
// checking, stack frames, assertions, and
|
||||
// other debugging options will be turned on.
|
||||
{$DEFINE IMAGING_RELEASE} // If defined, all debug info is off.
|
||||
|
||||
|
||||
|
||||
(* File format support linking options.
|
||||
Define formats which you don't want to be registred automatically.
|
||||
Default: all formats are registered = no symbols defined.
|
||||
Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line
|
||||
*)
|
||||
|
||||
{$DEFINE DONT_LINK_JPEG} // link support for Jpeg images
|
||||
{.$DEFINE DONT_LINK_PNG} // link support for PNG images
|
||||
{.$DEFINE DONT_LINK_TARGA} // link support for Targa images
|
||||
{.$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images
|
||||
{$DEFINE DONT_LINK_DDS} // link support for DDS images
|
||||
{$DEFINE DONT_LINK_GIF} // link support for GIF images
|
||||
{$DEFINE DONT_LINK_MNG} // link support for MNG images
|
||||
{$DEFINE DONT_LINK_JNG} // link support for JNG images
|
||||
{$DEFINE DONT_LINK_PNM} // link support for PortableMap images (PBM, PGM, PPM, PAM, PFM)
|
||||
|
||||
{$DEFINE DONT_LINK_EXTRAS} // link support for file formats defined in
|
||||
// Extras package. Exactly which formats will be
|
||||
// registered depends on settings in
|
||||
// ImagingExtras.pas unit.
|
||||
|
||||
{ Component set used in ImagignComponents.pas unit. You usually don't need
|
||||
to be concerned with this - proper component library is selected automatically
|
||||
according to your compiler. }
|
||||
|
||||
{ $DEFINE COMPONENT_SET_VCL} // use Delphi VCL
|
||||
{$DEFINE COMPONENT_SET_LCL} // use Lazarus LCL (set automatically when compiling with FPC)
|
||||
|
||||
{
|
||||
Auto Options
|
||||
Following options and defines are set automatically and some
|
||||
are required for Imaging to compile successfully. Do not change
|
||||
anything here if you don't know what you are doing.
|
||||
}
|
||||
|
||||
{ Compiler options }
|
||||
|
||||
{$ALIGN ON} // Field alignment: 8 Bytes (in D6+)
|
||||
{$BOOLEVAL OFF} // Boolean eval: off
|
||||
{$EXTENDEDSYNTAX ON} // Extended syntax: on
|
||||
{$LONGSTRINGS ON} // string = AnsiString: on
|
||||
{$MINENUMSIZE 4} // Min enum size: 4 B
|
||||
{$TYPEDADDRESS OFF} // Typed pointers: off
|
||||
{$WRITEABLECONST OFF} // Writeable constants: off
|
||||
|
||||
{$IFNDEF FPC}
|
||||
{$DEFINE DCC} // if not using FPC then DCC compiler is used (Delphi/Kylix)
|
||||
// others are not supported
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DCC}
|
||||
{$IFDEF LINUX}
|
||||
{$DEFINE KYLIX} // using Kylix
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DCC}
|
||||
{$IFNDEF KYLIX}
|
||||
{$DEFINE DELPHI} // using Delphi
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IF Defined(IMAGING_DEBUG)}
|
||||
{$ASSERTIONS ON}
|
||||
{$DEBUGINFO ON}
|
||||
{$RANGECHECKS ON}
|
||||
{$IOCHECKS ON}
|
||||
{$OVERFLOWCHECKS ON}
|
||||
{$IFDEF DCC}
|
||||
{$OPTIMIZATION OFF}
|
||||
{$STACKFRAMES ON}
|
||||
{$LOCALSYMBOLS ON}
|
||||
{$DEFINE MEMCHECK}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC}
|
||||
{$S+}
|
||||
{$CHECKPOINTER ON}
|
||||
{$ENDIF}
|
||||
{$ELSEIF Defined(IMAGING_RELEASE)}
|
||||
{$ASSERTIONS OFF}
|
||||
{$DEBUGINFO OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IOCHECKS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$IFDEF DCC}
|
||||
{$OPTIMIZATION ON}
|
||||
{$STACKFRAMES OFF}
|
||||
{$LOCALSYMBOLS OFF}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC}
|
||||
{$S-}
|
||||
{$ENDIF}
|
||||
{$IFEND}
|
||||
|
||||
|
||||
{ Compiler capabilities }
|
||||
|
||||
// Define if compiler supports inlining of functions and procedures
|
||||
// Note that FPC inline support crashed in older versions (1.9.8)
|
||||
{$IF (Defined(FPC) and Defined(CPU86))}
|
||||
{$DEFINE HAS_INLINE}
|
||||
{$IFEND}
|
||||
|
||||
// Define if compiler supports operator overloading
|
||||
// (unfortunately Delphi and FPC operator overloaing is not compatible)
|
||||
{$IF Defined(FPC)}
|
||||
{$DEFINE HAS_OPERATOR_OVERLOADING}
|
||||
{$IFEND}
|
||||
|
||||
{ Imaging options check}
|
||||
|
||||
{$IFNDEF HAS_INLINE}
|
||||
{$UNDEF USE_INLINE}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$IFNDEF CPU86}
|
||||
{$UNDEF USE_ASM}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$DEFINE COMPONENT_SET_LCL}
|
||||
{$UNDEF COMPONENT_SET_VCL}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI}
|
||||
{$UNDEF COMPONENT_SET_LCL}
|
||||
{$DEFINE COMPONENT_SET_VCL}
|
||||
{$ENDIF}
|
||||
|
||||
{ Platform options }
|
||||
|
||||
{$IFDEF WIN32}
|
||||
{$DEFINE MSWINDOWS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DPMI}
|
||||
{$DEFINE MSDOS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
{$DEFINE UNIX}
|
||||
{$ENDIF}
|
||||
|
||||
{ More compiler options }
|
||||
|
||||
{$IFDEF FPC} // Free Pascal options - some options set above (like min enum size)
|
||||
// are reset to defaults by setting {$MODE} so they are
|
||||
// redeclared here
|
||||
{$MODE DELPHI} // compatible with delphi
|
||||
{$GOTO ON} // alow goto
|
||||
{$PACKRECORDS 8} // same as ALING 8 for Delphi
|
||||
{$PACKENUM 4} // Min enum size: 4 B
|
||||
{$CALLING REGISTER} // default calling convention is register
|
||||
{$IFDEF CPU86}
|
||||
{$ASMMODE INTEL} // intel assembler mode
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF HAS_INLINE}
|
||||
{$INLINE ON} // turns inlining on for compilers that support it
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
{
|
||||
User Options
|
||||
Following defines and options can be changed by user.
|
||||
}
|
||||
|
||||
{ Source options }
|
||||
|
||||
{$DEFINE USE_INLINE} // Use function inlining for some functions
|
||||
// works in Free Pascal and Delphi 9+.
|
||||
{$DEFINE USE_ASM} // If defined, assembler versions of some
|
||||
// functions will be used (only for x86).
|
||||
|
||||
// Debug options: If none of these two are defined
|
||||
// your project settings are used.
|
||||
{.$DEFINE IMAGING_DEBUG} // If defined, debug info, range/IO/overflow
|
||||
// checking, stack frames, assertions, and
|
||||
// other debugging options will be turned on.
|
||||
{$DEFINE IMAGING_RELEASE} // If defined, all debug info is off.
|
||||
|
||||
{$DEFINE OPENGL_NO_EXT_HEADERS}
|
||||
|
||||
|
||||
|
||||
(* File format support linking options.
|
||||
Define formats which you don't want to be registered automatically (by adding
|
||||
Imaging.pas unit to your uses clause).
|
||||
Default: most formats are registered = no symbols defined.
|
||||
Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line
|
||||
*)
|
||||
|
||||
{$DEFINE DONT_LINK_JPEG} // link support for Jpeg images
|
||||
{.$DEFINE DONT_LINK_PNG} // link support for PNG images
|
||||
{.$DEFINE DONT_LINK_TARGA} // link support for Targa images
|
||||
{.$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images
|
||||
{$DEFINE DONT_LINK_DDS} // link support for DDS images
|
||||
{$DEFINE DONT_LINK_GIF} // link support for GIF images
|
||||
{$DEFINE DONT_LINK_MNG} // link support for MNG images
|
||||
{$DEFINE DONT_LINK_JNG} // link support for JNG images
|
||||
{$DEFINE DONT_LINK_PNM} // link support for PortableMap images (PBM, PGM, PPM, PAM, PFM)
|
||||
{$DEFINE DONT_LINK_RADHDR} // link support for Radiance HDR/RGBE file format
|
||||
|
||||
{$DEFINE DONT_LINK_EXTRAS} // link support for file formats defined in
|
||||
// Extensions package. Exactly which formats will be
|
||||
// registered depends on settings in
|
||||
// ImagingExtFileFormats.pas unit.
|
||||
|
||||
{.$DEFINE DONT_LINK_FILE_FORMATS} // no auto link support of any file format
|
||||
|
||||
{
|
||||
Auto Options
|
||||
Following options and defines are set automatically and some
|
||||
are required for Imaging to compile successfully. Do not change
|
||||
anything here if you don't know what you are doing.
|
||||
}
|
||||
|
||||
{ Compiler options }
|
||||
|
||||
{$ALIGN ON} // Field alignment: 8 Bytes (in D6+)
|
||||
{$BOOLEVAL OFF} // Boolean eval: off
|
||||
{$EXTENDEDSYNTAX ON} // Extended syntax: on
|
||||
{$LONGSTRINGS ON} // string = AnsiString: on
|
||||
{$MINENUMSIZE 1} // Min enum size: 1 B
|
||||
{$TYPEDADDRESS OFF} // Typed pointers: off
|
||||
{$WRITEABLECONST OFF} // Writeable constants: off
|
||||
|
||||
{$IFNDEF FPC}
|
||||
{$DEFINE DCC} // if not using FPC then DCC compiler is used (Delphi/BCB)
|
||||
// others are not supported
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DCC}
|
||||
{$DEFINE DELPHI}
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 25.0))}
|
||||
{$LEGACYIFEND ON}
|
||||
{$IFEND}
|
||||
{$ENDIF}
|
||||
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 18.5))}
|
||||
{$IFDEF RELEASE}
|
||||
{$UNDEF DEBUG} // If we are using Delphi 2007+ where you can set
|
||||
// DEBUG/RELEASE mode in project options and RELEASE
|
||||
// is currently set we undef DEBUG mode
|
||||
{$ENDIF}
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(IMAGING_DEBUG)}
|
||||
{$ASSERTIONS ON}
|
||||
{$DEBUGINFO ON}
|
||||
{$RANGECHECKS ON}
|
||||
{$IOCHECKS ON}
|
||||
{$OVERFLOWCHECKS ON}
|
||||
{$IFDEF DCC}
|
||||
{$OPTIMIZATION OFF}
|
||||
{$STACKFRAMES ON}
|
||||
{$LOCALSYMBOLS ON}
|
||||
{$DEFINE MEMCHECK}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC}
|
||||
{$S+}
|
||||
{$CHECKPOINTER ON}
|
||||
{$ENDIF}
|
||||
{$ELSEIF Defined(IMAGING_RELEASE)}
|
||||
{$ASSERTIONS OFF}
|
||||
{$DEBUGINFO OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$IOCHECKS OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$IFDEF DCC}
|
||||
{$OPTIMIZATION ON}
|
||||
{$STACKFRAMES OFF}
|
||||
{$LOCALSYMBOLS OFF}
|
||||
{$ENDIF}
|
||||
{$IFDEF FPC}
|
||||
{$S-}
|
||||
{$ENDIF}
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(CPU86) and not Defined(CPUX86)}
|
||||
{$DEFINE CPUX86} // Compatibility with Delphi
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(CPUX86_64) and not Defined(CPUX64)}
|
||||
{$DEFINE CPUX64} // Compatibility with Delphi
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(DARWIN) and not Defined(MACOS)}
|
||||
{$DEFINE MACOS} // Compatibility with Delphi
|
||||
{$IFEND}
|
||||
{$IF Defined(MACOS)}
|
||||
{$DEFINE MACOSX}
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(DCC) and (CompilerVersion < 23)} // < XE2
|
||||
{$DEFINE CPUX86} // Compatibility with older Delphi
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(WIN32) or Defined(WIN64)}
|
||||
{$DEFINE MSWINDOWS} // Compatibility with Delphi
|
||||
{$IFEND}
|
||||
|
||||
{$IF Defined(UNIX) and not Defined(POSIX)}
|
||||
{$DEFINE POSIX} // Compatibility with Delphi
|
||||
{$IFEND}
|
||||
|
||||
{ Compiler capabilities }
|
||||
|
||||
// Define if compiler supports inlining of functions and procedures
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 17)) or Defined(FPC)}
|
||||
{$DEFINE HAS_INLINE}
|
||||
{$IFEND}
|
||||
|
||||
// Define if compiler supports advanced records with methods
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 18)) or
|
||||
(Defined(FPC) and (FPC_FULLVERSION >= 20600))}
|
||||
{$DEFINE HAS_ADVANCED_RECORDS}
|
||||
{$IFEND}
|
||||
|
||||
// Define if compiler supports operator overloading
|
||||
// (unfortunately Delphi and FPC operator overloading is not compatible).
|
||||
// FPC supports Delphi compatible operator overloads since 2.6.0
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 18)) or
|
||||
(Defined(FPC) and (FPC_FULLVERSION >= 20600))}
|
||||
{$DEFINE HAS_OPERATOR_OVERLOADING}
|
||||
{$IFEND}
|
||||
|
||||
// Anonymous methods
|
||||
{$IF Defined(DCC) and (CompilerVersion >= 20) }
|
||||
{$DEFINE HAS_ANON_METHODS}
|
||||
{$IFEND}
|
||||
|
||||
// Generic types (Delphi and FPC implementations incompatible).
|
||||
// Update: FPC supports Delphi compatible generics since 2.6.0
|
||||
{$IF (Defined(DCC) and (CompilerVersion >= 20)) or
|
||||
(Defined(FPC) and (FPC_FULLVERSION >= 20600))}
|
||||
{$DEFINE HAS_GENERICS}
|
||||
{$IFEND}
|
||||
|
||||
{ Compiler pecularities }
|
||||
|
||||
// Delphi 64bit POSIX targets
|
||||
{$IF Defined(DCC) and (SizeOf(Integer) <> SizeOf(LongInt))}
|
||||
{$DEFINE LONGINT_IS_NOT_INTEGER}
|
||||
{$IFEND}
|
||||
|
||||
// They used to force IFEND, now they warn about it
|
||||
{$IF Defined(DCC) and (CompilerVersion >= 33)}
|
||||
{$LEGACYIFEND ON}
|
||||
{$IFEND}
|
||||
|
||||
{ Imaging options check}
|
||||
|
||||
{$IFNDEF HAS_INLINE}
|
||||
{$UNDEF USE_INLINE}
|
||||
{$ENDIF}
|
||||
|
||||
{$IF not Defined(CPUX86)}
|
||||
{$UNDEF USE_ASM}
|
||||
{$IFEND}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$DEFINE COMPONENT_SET_LCL}
|
||||
{$UNDEF COMPONENT_SET_VCL}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI}
|
||||
{$UNDEF COMPONENT_SET_LCL}
|
||||
{$DEFINE COMPONENT_SET_VCL}
|
||||
{$ENDIF}
|
||||
|
||||
{ More compiler options }
|
||||
|
||||
{$IFDEF FPC} // Free Pascal options - some options set above (like min enum size)
|
||||
// are reset to defaults by setting {$MODE} so they are
|
||||
// redeclared here
|
||||
{$MODE DELPHI} // compatible with delphi
|
||||
{$GOTO ON} // alow goto
|
||||
{$PACKRECORDS 8} // same as ALING 8 for Delphi
|
||||
{$PACKENUM 4} // Min enum size: 4 B
|
||||
{$IFDEF CPU86}
|
||||
{$ASMMODE INTEL} // intel assembler mode
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF HAS_INLINE}
|
||||
{$INLINE ON} // turns inlining on for compilers that support it
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
480
Imaging/ImagingRadiance.pas
Normal file
480
Imaging/ImagingRadiance.pas
Normal file
@ -0,0 +1,480 @@
|
||||
{
|
||||
Vampyre Imaging Library
|
||||
by Marek Mauder
|
||||
https://github.com/galfar/imaginglib
|
||||
https://imaginglib.sourceforge.io
|
||||
- - - - -
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0.
|
||||
}
|
||||
|
||||
{ This unit contains image format loader/saver for Radiance HDR/RGBE images.}
|
||||
unit ImagingRadiance;
|
||||
|
||||
{$I ImagingOptions.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, Imaging, ImagingTypes, ImagingUtility;
|
||||
|
||||
type
|
||||
{ Radiance is a suite of tools for performing lighting simulation. It's
|
||||
development started in 1985 and it pioneered the concept of
|
||||
high dynamic range imaging. Radiance defined an image format for storing
|
||||
HDR images, now described as RGBE image format. Since it was the first
|
||||
HDR image format, this format is supported by many other software packages.
|
||||
|
||||
Radiance image file consists of three sections: a header, resolution string,
|
||||
followed by the pixel data. Each pixel is stored as 4 bytes, one byte
|
||||
mantissa for each r, g, b and a shared one byte exponent.
|
||||
The pixel data may be stored uncompressed or using run length encoding.
|
||||
|
||||
Imaging translates RGBE pixels to original float values and stores them
|
||||
in ifR32G32B32F data format. It can read both compressed and uncompressed
|
||||
files, and saves files as compressed.}
|
||||
THdrFileFormat = class(TImageFileFormat)
|
||||
protected
|
||||
procedure Define; override;
|
||||
function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray;
|
||||
OnlyFirstLevel: Boolean): Boolean; override;
|
||||
function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray;
|
||||
Index: LongInt): Boolean; override;
|
||||
procedure ConvertToSupported(var Image: TImageData;
|
||||
const Info: TImageFormatInfo); override;
|
||||
public
|
||||
function TestFormat(Handle: TImagingHandle): Boolean; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math, ImagingIO;
|
||||
|
||||
const
|
||||
SHdrFormatName = 'Radiance HDR/RGBE';
|
||||
SHdrMasks = '*.hdr';
|
||||
HdrSupportedFormats: TImageFormats = [ifR32G32B32F];
|
||||
|
||||
type
|
||||
TSignature = array[0..9] of AnsiChar;
|
||||
THdrFormat = (hfRgb, hfXyz);
|
||||
|
||||
THdrHeader = record
|
||||
Format: THdrFormat;
|
||||
Width: Integer;
|
||||
Height: Integer;
|
||||
end;
|
||||
|
||||
TRgbe = packed record
|
||||
R, G, B, E: Byte;
|
||||
end;
|
||||
TDynRgbeArray = array of TRgbe;
|
||||
|
||||
const
|
||||
RadianceSignature: TSignature = '#?RADIANCE';
|
||||
RgbeSignature: TSignature = '#?RGBE';
|
||||
SFmtRgbeRle = '32-bit_rle_rgbe';
|
||||
SFmtXyzeRle = '32-bit_rle_xyze';
|
||||
|
||||
resourcestring
|
||||
SErrorBadHeader = 'Bad HDR/RGBE header format.';
|
||||
SWrongScanLineWidth = 'Wrong scanline width.';
|
||||
SXyzNotSupported = 'XYZ color space not supported.';
|
||||
|
||||
{ THdrFileFormat }
|
||||
|
||||
procedure THdrFileFormat.Define;
|
||||
begin
|
||||
inherited;
|
||||
FName := SHdrFormatName;
|
||||
FFeatures := [ffLoad, ffSave];
|
||||
FSupportedFormats := HdrSupportedFormats;
|
||||
|
||||
AddMasks(SHdrMasks);
|
||||
end;
|
||||
|
||||
function THdrFileFormat.LoadData(Handle: TImagingHandle;
|
||||
var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean;
|
||||
var
|
||||
Header: THdrHeader;
|
||||
IO: TIOFunctions;
|
||||
|
||||
function ReadHeader: Boolean;
|
||||
const
|
||||
CommentIds: TAnsiCharSet = ['#', '!'];
|
||||
var
|
||||
Line: AnsiString;
|
||||
HasResolution: Boolean;
|
||||
Count, Idx: Integer;
|
||||
ValStr, NativeLine: string;
|
||||
ValFloat: Double;
|
||||
begin
|
||||
Result := False;
|
||||
HasResolution := False;
|
||||
Count := 0;
|
||||
|
||||
repeat
|
||||
if not ReadLine(IO, Handle, Line) then
|
||||
Exit;
|
||||
|
||||
Inc(Count);
|
||||
if Count > 16 then // Too long header for HDR
|
||||
Exit;
|
||||
|
||||
if Length(Line) = 0 then
|
||||
Continue;
|
||||
if Line[1] in CommentIds then
|
||||
Continue;
|
||||
|
||||
NativeLine := string(Line);
|
||||
|
||||
if StrMaskMatch(NativeLine, 'Format=*') then
|
||||
begin
|
||||
// Data format parsing
|
||||
ValStr := Copy(NativeLine, 8, MaxInt);
|
||||
if ValStr = SFmtRgbeRle then
|
||||
Header.Format := hfRgb
|
||||
else if ValStr = SFmtXyzeRle then
|
||||
Header.Format := hfXyz
|
||||
else
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if StrMaskMatch(NativeLine, 'Gamma=*') then
|
||||
begin
|
||||
ValStr := Copy(NativeLine, 7, MaxInt);
|
||||
if TryStrToFloat(ValStr, ValFloat, GetFormatSettingsForFloats) then
|
||||
FMetadata.SetMetaItem(SMetaGamma, ValFloat);
|
||||
end;
|
||||
|
||||
if StrMaskMatch(NativeLine, 'Exposure=*') then
|
||||
begin
|
||||
ValStr := Copy(NativeLine, 10, MaxInt);
|
||||
if TryStrToFloat(ValStr, ValFloat, GetFormatSettingsForFloats) then
|
||||
FMetadata.SetMetaItem(SMetaExposure, ValFloat);
|
||||
end;
|
||||
|
||||
if StrMaskMatch(NativeLine, '?Y * ?X *') then
|
||||
begin
|
||||
Idx := Pos('X', NativeLine);
|
||||
ValStr := SubString(NativeLine, 4, Idx - 2);
|
||||
if not TryStrToInt(ValStr, Header.Height) then
|
||||
Exit;
|
||||
ValStr := Copy(NativeLine, Idx + 2, MaxInt);
|
||||
if not TryStrToInt(ValStr, Header.Width) then
|
||||
Exit;
|
||||
|
||||
if (NativeLine[1] = '-') then
|
||||
Header.Height := -Header.Height;
|
||||
if (NativeLine[Idx - 1] = '-') then
|
||||
Header.Width := -Header.Width;
|
||||
|
||||
HasResolution := True;
|
||||
end;
|
||||
|
||||
until HasResolution;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure DecodeRgbe(const Src: TRgbe; Dest: PColor96FPRec); {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||
var
|
||||
Mult: Single;
|
||||
begin
|
||||
if Src.E > 0 then
|
||||
begin
|
||||
Mult := Math.Ldexp(1, Src.E - 128);
|
||||
Dest.R := Src.R / 255 * Mult;
|
||||
Dest.G := Src.G / 255 * Mult;
|
||||
Dest.B := Src.B / 255 * Mult;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Dest.R := 0;
|
||||
Dest.G := 0;
|
||||
Dest.B := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ReadCompressedLine(Width, Y: Integer; var DestBuffer: TDynRgbeArray);
|
||||
var
|
||||
Pos: Integer;
|
||||
I, X, Count: Integer;
|
||||
Code, Value: Byte;
|
||||
LineBuff: TDynByteArray;
|
||||
Rgbe: TRgbe;
|
||||
Ptr: PByte;
|
||||
begin
|
||||
SetLength(LineBuff, Width);
|
||||
IO.Read(Handle, @Rgbe, SizeOf(Rgbe));
|
||||
|
||||
if ((Rgbe.B shl 8) or Rgbe.E) <> Width then
|
||||
RaiseImaging(SWrongScanLineWidth);
|
||||
|
||||
for I := 0 to 3 do
|
||||
begin
|
||||
Pos := 0;
|
||||
while Pos < Width do
|
||||
begin
|
||||
IO.Read(Handle, @Code, SizeOf(Byte));
|
||||
if Code > 128 then
|
||||
begin
|
||||
Count := Code - 128;
|
||||
IO.Read(Handle, @Value, SizeOf(Byte));
|
||||
FillMemoryByte(@LineBuff[Pos], Count, Value);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Count := Code;
|
||||
IO.Read(Handle, @LineBuff[Pos], Count * SizeOf(Byte));
|
||||
end;
|
||||
Inc(Pos, Count);
|
||||
end;
|
||||
|
||||
Ptr := @PByteArray(@DestBuffer[0])[I];
|
||||
for X := 0 to Width - 1 do
|
||||
begin
|
||||
Ptr^ := LineBuff[X];
|
||||
Inc(Ptr, 4);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ReadPixels(var Image: TImageData);
|
||||
var
|
||||
Y, X, SrcLineLen: Integer;
|
||||
Dest: PColor96FPRec;
|
||||
Compressed: Boolean;
|
||||
Rgbe: TRgbe;
|
||||
Buffer: TDynRgbeArray;
|
||||
begin
|
||||
Dest := Image.Bits;
|
||||
Compressed := not ((Image.Width < 8) or (Image.Width > $7FFFF));
|
||||
SrcLineLen := Image.Width * SizeOf(TRgbe);
|
||||
|
||||
IO.Read(Handle, @Rgbe, SizeOf(Rgbe));
|
||||
IO.Seek(Handle, -SizeOf(Rgbe), smFromCurrent);
|
||||
|
||||
if (Rgbe.R <> 2) or (Rgbe.G <> 2) or ((Rgbe.B and 128) > 0) then
|
||||
Compressed := False;
|
||||
|
||||
SetLength(Buffer, Image.Width);
|
||||
|
||||
for Y := 0 to Image.Height - 1 do
|
||||
begin
|
||||
if Compressed then
|
||||
ReadCompressedLine(Image.Width, Y, Buffer)
|
||||
else
|
||||
IO.Read(Handle, @Buffer[0], SrcLineLen);
|
||||
|
||||
for X := 0 to Image.Width - 1 do
|
||||
begin
|
||||
DecodeRgbe(Buffer[X], Dest);
|
||||
Inc(Dest);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
IO := GetIO;
|
||||
SetLength(Images, 1);
|
||||
|
||||
// Read header, allocate new image and, then read and convert the pixels
|
||||
if not ReadHeader then
|
||||
RaiseImaging(SErrorBadHeader);
|
||||
if (Header.Format = hfXyz) then
|
||||
RaiseImaging(SXyzNotSupported);
|
||||
|
||||
NewImage(Abs(Header.Width), Abs(Header.Height), ifR32G32B32F, Images[0]);
|
||||
ReadPixels(Images[0]);
|
||||
|
||||
// Flip/mirror the image as needed (height < 0 is default top-down)
|
||||
if Header.Width < 0 then
|
||||
MirrorImage(Images[0]);
|
||||
if Header.Height > 0 then
|
||||
FlipImage(Images[0]);
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function THdrFileFormat.SaveData(Handle: TImagingHandle;
|
||||
const Images: TDynImageDataArray; Index: LongInt): Boolean;
|
||||
const
|
||||
LineEnd = #$0A;
|
||||
SPrgComment = '#Made with Vampyre Imaging Library';
|
||||
SSizeFmt = '-Y %d +X %d';
|
||||
var
|
||||
ImageToSave: TImageData;
|
||||
MustBeFreed: Boolean;
|
||||
IO: TIOFunctions;
|
||||
|
||||
procedure SaveHeader;
|
||||
begin
|
||||
WriteLine(IO, Handle, RadianceSignature, LineEnd);
|
||||
WriteLine(IO, Handle, SPrgComment, LineEnd);
|
||||
WriteLine(IO, Handle, 'FORMAT=' + SFmtRgbeRle, LineEnd + LineEnd);
|
||||
WriteLine(IO, Handle, AnsiString(Format(SSizeFmt, [ImageToSave.Height, ImageToSave.Width])), LineEnd);
|
||||
end;
|
||||
|
||||
procedure EncodeRgbe(const Src: TColor96FPRec; var DestR, DestG, DestB, DestE: Byte); {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||
var
|
||||
V, M: {$IFDEF FPC}Float{$ELSE}Extended{$ENDIF};
|
||||
E: Integer;
|
||||
begin
|
||||
V := Src.R;
|
||||
if (Src.G > V) then
|
||||
V := Src.G;
|
||||
if (Src.B > V) then
|
||||
V := Src.B;
|
||||
|
||||
if V < 1e-32 then
|
||||
begin
|
||||
DestR := 0;
|
||||
DestG := 0;
|
||||
DestB := 0;
|
||||
DestE := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Frexp(V, M, E);
|
||||
V := M * 256.0 / V;
|
||||
DestR := ClampToByte(Round(Src.R * V));
|
||||
DestG := ClampToByte(Round(Src.G * V));
|
||||
DestB := ClampToByte(Round(Src.B * V));
|
||||
DestE := ClampToByte(E + 128);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure WriteRleLine(const Line: array of Byte; Width: Integer);
|
||||
const
|
||||
MinRunLength = 4;
|
||||
var
|
||||
Cur, BeginRun, RunCount, OldRunCount, NonRunCount: Integer;
|
||||
Buf: array[0..1] of Byte;
|
||||
begin
|
||||
Cur := 0;
|
||||
while Cur < Width do
|
||||
begin
|
||||
BeginRun := Cur;
|
||||
RunCount := 0;
|
||||
OldRunCount := 0;
|
||||
while (RunCount < MinRunLength) and (BeginRun < Width) do
|
||||
begin
|
||||
Inc(BeginRun, RunCount);
|
||||
OldRunCount := RunCount;
|
||||
RunCount := 1;
|
||||
while (BeginRun + RunCount < Width) and (RunCount < 127) and (Line[BeginRun] = Line[BeginRun + RunCount]) do
|
||||
Inc(RunCount);
|
||||
end;
|
||||
if (OldRunCount > 1) and (OldRunCount = BeginRun - Cur) then
|
||||
begin
|
||||
Buf[0] := 128 + OldRunCount;
|
||||
Buf[1] := Line[Cur];
|
||||
IO.Write(Handle, @Buf, 2);
|
||||
Cur := BeginRun;
|
||||
end;
|
||||
while Cur < BeginRun do
|
||||
begin
|
||||
NonRunCount := Min(128, BeginRun - Cur);
|
||||
Buf[0] := NonRunCount;
|
||||
IO.Write(Handle, @Buf, 1);
|
||||
IO.Write(Handle, @Line[Cur], NonRunCount);
|
||||
Inc(Cur, NonRunCount);
|
||||
end;
|
||||
if RunCount >= MinRunLength then
|
||||
begin
|
||||
Buf[0] := 128 + RunCount;
|
||||
Buf[1] := Line[BeginRun];
|
||||
IO.Write(Handle, @Buf, 2);
|
||||
Inc(Cur, RunCount);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SavePixels;
|
||||
var
|
||||
Y, X, I, Width: Integer;
|
||||
SrcPtr: PColor96FPRecArray;
|
||||
Components: array of array of Byte;
|
||||
StartLine: array[0..3] of Byte;
|
||||
begin
|
||||
Width := ImageToSave.Width;
|
||||
// Save using RLE, each component is compressed separately
|
||||
SetLength(Components, 4, Width);
|
||||
|
||||
for Y := 0 to ImageToSave.Height - 1 do
|
||||
begin
|
||||
SrcPtr := @PColor96FPRecArray(ImageToSave.Bits)[ImageToSave.Width * Y];
|
||||
|
||||
// Identify line as using "new" RLE scheme (separate components)
|
||||
StartLine[0] := 2;
|
||||
StartLine[1] := 2;
|
||||
StartLine[2] := Width shr 8;
|
||||
StartLine[3] := Width and $FF;
|
||||
IO.Write(Handle, @StartLine, SizeOf(StartLine));
|
||||
|
||||
for X := 0 to Width - 1 do
|
||||
begin
|
||||
EncodeRgbe(SrcPtr[X], Components[0, X], Components[1, X],
|
||||
Components[2, X], Components[3, X]);
|
||||
end;
|
||||
|
||||
for I := 0 to 3 do
|
||||
WriteRleLine(Components[I], Width);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := False;
|
||||
IO := GetIO;
|
||||
// Makes image to save compatible with Jpeg saving capabilities
|
||||
if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then
|
||||
with ImageToSave do
|
||||
try
|
||||
// Save header
|
||||
SaveHeader;
|
||||
// Save uncompressed pixels
|
||||
SavePixels;
|
||||
Result := True;
|
||||
finally
|
||||
if MustBeFreed then
|
||||
FreeImage(ImageToSave);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure THdrFileFormat.ConvertToSupported(var Image: TImageData;
|
||||
const Info: TImageFormatInfo);
|
||||
begin
|
||||
ConvertImage(Image, ifR32G32B32F);
|
||||
end;
|
||||
|
||||
function THdrFileFormat.TestFormat(Handle: TImagingHandle): Boolean;
|
||||
var
|
||||
FileSig: TSignature;
|
||||
ReadCount: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if Handle <> nil then
|
||||
begin
|
||||
ReadCount := GetIO.Read(Handle, @FileSig, SizeOf(FileSig));
|
||||
GetIO.Seek(Handle, -ReadCount, smFromCurrent);
|
||||
Result := (ReadCount = SizeOf(FileSig)) and
|
||||
((FileSig = RadianceSignature) or CompareMem(@FileSig, @RgbeSignature, 6));
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterImageFileFormat(THdrFileFormat);
|
||||
|
||||
{
|
||||
File Notes:
|
||||
|
||||
-- 0.77.1 ---------------------------------------------------
|
||||
- Added RLE compression to saving.
|
||||
- Added image saving.
|
||||
- Unit created with initial stuff (loading only).
|
||||
|
||||
}
|
||||
|
||||
end.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,401 +1,400 @@
|
||||
unit imjcapimin;
|
||||
{$N+}
|
||||
{ This file contains application interface code for the compression half
|
||||
of the JPEG library. These are the "minimum" API routines that may be
|
||||
needed in either the normal full-compression case or the transcoding-only
|
||||
case.
|
||||
|
||||
Most of the routines intended to be called directly by an application
|
||||
are in this file or in jcapistd.c. But also see jcparam.c for
|
||||
parameter-setup helper routines, jcomapi.c for routines shared by
|
||||
compression and decompression, and jctrans.c for the transcoding case. }
|
||||
|
||||
{ jcapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. }
|
||||
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjcomapi,
|
||||
imjmemmgr,
|
||||
imjcmarker;
|
||||
|
||||
{ Initialization of JPEG compression objects.
|
||||
Nomssi: This is a macro in the original code.
|
||||
|
||||
jpeg_create_compress() and jpeg_create_decompress() are the exported
|
||||
names that applications should call. These expand to calls on
|
||||
jpeg_CreateCompress and jpeg_CreateDecompress with additional information
|
||||
passed for version mismatch checking.
|
||||
NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. }
|
||||
|
||||
procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Initialization of a JPEG compression object.
|
||||
The error manager must already be set up (in case memory manager fails). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
||||
version : int;
|
||||
structsize : size_t);
|
||||
|
||||
{ Destruction of a JPEG compression object }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Abort processing of a JPEG compression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Forcibly suppress or un-suppress all quantization and Huffman tables.
|
||||
Marks all currently defined tables as already written (if suppress)
|
||||
or not written (if !suppress). This will control whether they get emitted
|
||||
by a subsequent jpeg_start_compress call.
|
||||
|
||||
This routine is exported for use by applications that want to produce
|
||||
abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
|
||||
since it is called by jpeg_start_compress, we put it here --- otherwise
|
||||
jcparam.o would be linked whether the application used it or not. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
||||
suppress : boolean);
|
||||
|
||||
|
||||
{ Finish JPEG compression.
|
||||
|
||||
If a multipass operating mode was selected, this may do a great deal of
|
||||
work including most of the actual output. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
||||
|
||||
{ Write a special marker.
|
||||
This is only recommended for writing COM or APPn markers.
|
||||
Must be called after jpeg_start_compress() and before
|
||||
first call to jpeg_write_scanlines() or jpeg_write_raw_data(). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
dataptr : JOCTETptr;
|
||||
datalen : uInt);
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
datalen : uint);
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
||||
|
||||
{ Alternate compression function: just write an abbreviated table file.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
To produce a pair of files containing abbreviated tables and abbreviated
|
||||
image data, one would proceed as follows:
|
||||
|
||||
initialize JPEG object
|
||||
set JPEG parameters
|
||||
set destination to table file
|
||||
jpeg_write_tables(cinfo);
|
||||
set destination to image file
|
||||
jpeg_start_compress(cinfo, FALSE);
|
||||
write data...
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
jpeg_write_tables has the side effect of marking all tables written
|
||||
(same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
|
||||
will not re-emit the tables unless it is passed write_all_tables=TRUE. }
|
||||
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
||||
|
||||
implementation
|
||||
|
||||
procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_CreateCompress(cinfo, JPEG_LIB_VERSION,
|
||||
size_t(sizeof(jpeg_compress_struct)));
|
||||
end;
|
||||
|
||||
{ Initialization of a JPEG compression object.
|
||||
The error manager must already be set up (in case memory manager fails). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
||||
version : int;
|
||||
structsize : size_t);
|
||||
var
|
||||
i : int;
|
||||
var
|
||||
err : jpeg_error_mgr_ptr;
|
||||
client_data : voidp;
|
||||
begin
|
||||
|
||||
{ Guard against version mismatches between library and caller. }
|
||||
cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called }
|
||||
if (version <> JPEG_LIB_VERSION) then
|
||||
ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||
if (structsize <> SIZEOF(jpeg_compress_struct)) then
|
||||
ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE,
|
||||
int(SIZEOF(jpeg_compress_struct)), int(structsize));
|
||||
|
||||
{ For debugging purposes, we zero the whole master structure.
|
||||
But the application has already set the err pointer, and may have set
|
||||
client_data, so we have to save and restore those fields.
|
||||
Note: if application hasn't set client_data, tools like Purify may
|
||||
complain here. }
|
||||
|
||||
err := cinfo^.err;
|
||||
client_data := cinfo^.client_data; { ignore Purify complaint here }
|
||||
MEMZERO(cinfo, SIZEOF(jpeg_compress_struct));
|
||||
cinfo^.err := err;
|
||||
cinfo^.is_decompressor := FALSE;
|
||||
|
||||
{ Initialize a memory manager instance for this object }
|
||||
jinit_memory_mgr(j_common_ptr(cinfo));
|
||||
|
||||
{ Zero out pointers to permanent structures. }
|
||||
cinfo^.progress := NIL;
|
||||
cinfo^.dest := NIL;
|
||||
|
||||
cinfo^.comp_info := NIL;
|
||||
|
||||
for i := 0 to pred(NUM_QUANT_TBLS) do
|
||||
cinfo^.quant_tbl_ptrs[i] := NIL;
|
||||
|
||||
for i := 0 to pred(NUM_HUFF_TBLS) do
|
||||
begin
|
||||
cinfo^.dc_huff_tbl_ptrs[i] := NIL;
|
||||
cinfo^.ac_huff_tbl_ptrs[i] := NIL;
|
||||
end;
|
||||
|
||||
cinfo^.script_space := NIL;
|
||||
|
||||
cinfo^.input_gamma := 1.0; { in case application forgets }
|
||||
|
||||
{ OK, I'm ready }
|
||||
cinfo^.global_state := CSTATE_START;
|
||||
end;
|
||||
|
||||
|
||||
{ Destruction of a JPEG compression object }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_destroy(j_common_ptr(cinfo)); { use common routine }
|
||||
end;
|
||||
|
||||
|
||||
{ Abort processing of a JPEG compression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_abort(j_common_ptr(cinfo)); { use common routine }
|
||||
end;
|
||||
|
||||
|
||||
{ Forcibly suppress or un-suppress all quantization and Huffman tables.
|
||||
Marks all currently defined tables as already written (if suppress)
|
||||
or not written (if !suppress). This will control whether they get emitted
|
||||
by a subsequent jpeg_start_compress call.
|
||||
|
||||
This routine is exported for use by applications that want to produce
|
||||
abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
|
||||
since it is called by jpeg_start_compress, we put it here --- otherwise
|
||||
jcparam.o would be linked whether the application used it or not. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
||||
suppress : boolean);
|
||||
var
|
||||
i : int;
|
||||
qtbl : JQUANT_TBL_PTR;
|
||||
htbl : JHUFF_TBL_PTR;
|
||||
begin
|
||||
for i := 0 to pred(NUM_QUANT_TBLS) do
|
||||
begin
|
||||
qtbl := cinfo^.quant_tbl_ptrs[i];
|
||||
if (qtbl <> NIL) then
|
||||
qtbl^.sent_table := suppress;
|
||||
end;
|
||||
|
||||
for i := 0 to pred(NUM_HUFF_TBLS) do
|
||||
begin
|
||||
htbl := cinfo^.dc_huff_tbl_ptrs[i];
|
||||
if (htbl <> NIL) then
|
||||
htbl^.sent_table := suppress;
|
||||
htbl := cinfo^.ac_huff_tbl_ptrs[i];
|
||||
if (htbl <> NIL) then
|
||||
htbl^.sent_table := suppress;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Finish JPEG compression.
|
||||
|
||||
If a multipass operating mode was selected, this may do a great deal of
|
||||
work including most of the actual output. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
||||
var
|
||||
iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state = CSTATE_SCANNING) or
|
||||
(cinfo^.global_state = CSTATE_RAW_OK) then
|
||||
begin
|
||||
{ Terminate first pass }
|
||||
if (cinfo^.next_scanline < cinfo^.image_height) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA);
|
||||
cinfo^.master^.finish_pass (cinfo);
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> CSTATE_WRCOEFS) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Perform any remaining passes }
|
||||
while (not cinfo^.master^.is_last_pass) do
|
||||
begin
|
||||
cinfo^.master^.prepare_for_pass (cinfo);
|
||||
for iMCU_row := 0 to pred(cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (iMCU_row);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.total_iMCU_rows);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
{ We bypass the main controller and invoke coef controller directly;
|
||||
all work is being done from the coefficient buffer. }
|
||||
|
||||
if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(NIL))) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND);
|
||||
end;
|
||||
cinfo^.master^.finish_pass (cinfo);
|
||||
end;
|
||||
{ Write EOI, do final cleanup }
|
||||
cinfo^.marker^.write_file_trailer (cinfo);
|
||||
cinfo^.dest^.term_destination (cinfo);
|
||||
{ We can use jpeg_abort to release memory and reset global_state }
|
||||
jpeg_abort(j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
|
||||
{ Write a special marker.
|
||||
This is only recommended for writing COM or APPn markers.
|
||||
Must be called after jpeg_start_compress() and before
|
||||
first call to jpeg_write_scanlines() or jpeg_write_raw_data(). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
dataptr : JOCTETptr;
|
||||
datalen : uInt);
|
||||
var
|
||||
write_marker_byte : procedure(info : j_compress_ptr; val : int);
|
||||
begin
|
||||
if (cinfo^.next_scanline <> 0) or
|
||||
((cinfo^.global_state <> CSTATE_SCANNING) and
|
||||
(cinfo^.global_state <> CSTATE_RAW_OK) and
|
||||
(cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
cinfo^.marker^.write_marker_header (cinfo, marker, datalen);
|
||||
write_marker_byte := cinfo^.marker^.write_marker_byte; { copy for speed }
|
||||
while (datalen <> 0) do
|
||||
begin
|
||||
Dec(datalen);
|
||||
write_marker_byte (cinfo, dataptr^);
|
||||
Inc(dataptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Same, but piecemeal. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
datalen : uint);
|
||||
begin
|
||||
if (cinfo^.next_scanline <> 0) or
|
||||
((cinfo^.global_state <> CSTATE_SCANNING) and
|
||||
(cinfo^.global_state <> CSTATE_RAW_OK) and
|
||||
(cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
cinfo^.marker^.write_marker_header (cinfo, marker, datalen);
|
||||
end;
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
||||
begin
|
||||
cinfo^.marker^.write_marker_byte (cinfo, val);
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate compression function: just write an abbreviated table file.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
To produce a pair of files containing abbreviated tables and abbreviated
|
||||
image data, one would proceed as follows:
|
||||
|
||||
initialize JPEG object
|
||||
set JPEG parameters
|
||||
set destination to table file
|
||||
jpeg_write_tables(cinfo);
|
||||
set destination to image file
|
||||
jpeg_start_compress(cinfo, FALSE);
|
||||
write data...
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
jpeg_write_tables has the side effect of marking all tables written
|
||||
(same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
|
||||
will not re-emit the tables unless it is passed write_all_tables=TRUE. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_START) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
{ (Re)initialize error mgr and destination modules }
|
||||
cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo));
|
||||
cinfo^.dest^.init_destination (cinfo);
|
||||
{ Initialize the marker writer ... bit of a crock to do it here. }
|
||||
jinit_marker_writer(cinfo);
|
||||
{ Write them tables! }
|
||||
cinfo^.marker^.write_tables_only (cinfo);
|
||||
{ And clean up. }
|
||||
cinfo^.dest^.term_destination (cinfo);
|
||||
|
||||
{ In library releases up through v6a, we called jpeg_abort() here to free
|
||||
any working memory allocated by the destination manager and marker
|
||||
writer. Some applications had a problem with that: they allocated space
|
||||
of their own from the library memory manager, and didn't want it to go
|
||||
away during write_tables. So now we do nothing. This will cause a
|
||||
memory leak if an app calls write_tables repeatedly without doing a full
|
||||
compression cycle or otherwise resetting the JPEG object. However, that
|
||||
seems less bad than unexpectedly freeing memory in the normal case.
|
||||
An app that prefers the old behavior can call jpeg_abort for itself after
|
||||
each call to jpeg_write_tables(). }
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcapimin;
|
||||
|
||||
{ This file contains application interface code for the compression half
|
||||
of the JPEG library. These are the "minimum" API routines that may be
|
||||
needed in either the normal full-compression case or the transcoding-only
|
||||
case.
|
||||
|
||||
Most of the routines intended to be called directly by an application
|
||||
are in this file or in jcapistd.c. But also see jcparam.c for
|
||||
parameter-setup helper routines, jcomapi.c for routines shared by
|
||||
compression and decompression, and jctrans.c for the transcoding case. }
|
||||
|
||||
{ jcapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. }
|
||||
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjcomapi,
|
||||
imjmemmgr,
|
||||
imjcmarker;
|
||||
|
||||
{ Initialization of JPEG compression objects.
|
||||
Nomssi: This is a macro in the original code.
|
||||
|
||||
jpeg_create_compress() and jpeg_create_decompress() are the exported
|
||||
names that applications should call. These expand to calls on
|
||||
jpeg_CreateCompress and jpeg_CreateDecompress with additional information
|
||||
passed for version mismatch checking.
|
||||
NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. }
|
||||
|
||||
procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Initialization of a JPEG compression object.
|
||||
The error manager must already be set up (in case memory manager fails). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
||||
version : int;
|
||||
structsize : size_t);
|
||||
|
||||
{ Destruction of a JPEG compression object }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Abort processing of a JPEG compression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
||||
|
||||
|
||||
{ Forcibly suppress or un-suppress all quantization and Huffman tables.
|
||||
Marks all currently defined tables as already written (if suppress)
|
||||
or not written (if !suppress). This will control whether they get emitted
|
||||
by a subsequent jpeg_start_compress call.
|
||||
|
||||
This routine is exported for use by applications that want to produce
|
||||
abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
|
||||
since it is called by jpeg_start_compress, we put it here --- otherwise
|
||||
jcparam.o would be linked whether the application used it or not. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
||||
suppress : boolean);
|
||||
|
||||
|
||||
{ Finish JPEG compression.
|
||||
|
||||
If a multipass operating mode was selected, this may do a great deal of
|
||||
work including most of the actual output. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
||||
|
||||
{ Write a special marker.
|
||||
This is only recommended for writing COM or APPn markers.
|
||||
Must be called after jpeg_start_compress() and before
|
||||
first call to jpeg_write_scanlines() or jpeg_write_raw_data(). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
dataptr : JOCTETptr;
|
||||
datalen : uInt);
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
datalen : uint);
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
||||
|
||||
{ Alternate compression function: just write an abbreviated table file.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
To produce a pair of files containing abbreviated tables and abbreviated
|
||||
image data, one would proceed as follows:
|
||||
|
||||
initialize JPEG object
|
||||
set JPEG parameters
|
||||
set destination to table file
|
||||
jpeg_write_tables(cinfo);
|
||||
set destination to image file
|
||||
jpeg_start_compress(cinfo, FALSE);
|
||||
write data...
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
jpeg_write_tables has the side effect of marking all tables written
|
||||
(same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
|
||||
will not re-emit the tables unless it is passed write_all_tables=TRUE. }
|
||||
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
||||
|
||||
implementation
|
||||
|
||||
procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_CreateCompress(cinfo, JPEG_LIB_VERSION,
|
||||
size_t(sizeof(jpeg_compress_struct)));
|
||||
end;
|
||||
|
||||
{ Initialization of a JPEG compression object.
|
||||
The error manager must already be set up (in case memory manager fails). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
||||
version : int;
|
||||
structsize : size_t);
|
||||
var
|
||||
i : int;
|
||||
var
|
||||
err : jpeg_error_mgr_ptr;
|
||||
client_data : voidp;
|
||||
begin
|
||||
|
||||
{ Guard against version mismatches between library and caller. }
|
||||
cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called }
|
||||
if (version <> JPEG_LIB_VERSION) then
|
||||
ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||
if (structsize <> SIZEOF(jpeg_compress_struct)) then
|
||||
ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE,
|
||||
int(SIZEOF(jpeg_compress_struct)), int(structsize));
|
||||
|
||||
{ For debugging purposes, we zero the whole master structure.
|
||||
But the application has already set the err pointer, and may have set
|
||||
client_data, so we have to save and restore those fields. }
|
||||
|
||||
err := cinfo^.err;
|
||||
client_data := cinfo^.client_data;
|
||||
MEMZERO(cinfo, SIZEOF(jpeg_compress_struct));
|
||||
cinfo^.err := err;
|
||||
cinfo^.is_decompressor := FALSE;
|
||||
cinfo^.client_data := client_data;
|
||||
|
||||
{ Initialize a memory manager instance for this object }
|
||||
jinit_memory_mgr(j_common_ptr(cinfo));
|
||||
|
||||
{ Zero out pointers to permanent structures. }
|
||||
cinfo^.progress := NIL;
|
||||
cinfo^.dest := NIL;
|
||||
|
||||
cinfo^.comp_info := NIL;
|
||||
|
||||
for i := 0 to pred(NUM_QUANT_TBLS) do
|
||||
cinfo^.quant_tbl_ptrs[i] := NIL;
|
||||
|
||||
for i := 0 to pred(NUM_HUFF_TBLS) do
|
||||
begin
|
||||
cinfo^.dc_huff_tbl_ptrs[i] := NIL;
|
||||
cinfo^.ac_huff_tbl_ptrs[i] := NIL;
|
||||
end;
|
||||
|
||||
cinfo^.script_space := NIL;
|
||||
|
||||
cinfo^.input_gamma := 1.0; { in case application forgets }
|
||||
|
||||
{ OK, I'm ready }
|
||||
cinfo^.global_state := CSTATE_START;
|
||||
end;
|
||||
|
||||
|
||||
{ Destruction of a JPEG compression object }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_destroy(j_common_ptr(cinfo)); { use common routine }
|
||||
end;
|
||||
|
||||
|
||||
{ Abort processing of a JPEG compression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
||||
begin
|
||||
jpeg_abort(j_common_ptr(cinfo)); { use common routine }
|
||||
end;
|
||||
|
||||
|
||||
{ Forcibly suppress or un-suppress all quantization and Huffman tables.
|
||||
Marks all currently defined tables as already written (if suppress)
|
||||
or not written (if !suppress). This will control whether they get emitted
|
||||
by a subsequent jpeg_start_compress call.
|
||||
|
||||
This routine is exported for use by applications that want to produce
|
||||
abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
|
||||
since it is called by jpeg_start_compress, we put it here --- otherwise
|
||||
jcparam.o would be linked whether the application used it or not. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
||||
suppress : boolean);
|
||||
var
|
||||
i : int;
|
||||
qtbl : JQUANT_TBL_PTR;
|
||||
htbl : JHUFF_TBL_PTR;
|
||||
begin
|
||||
for i := 0 to pred(NUM_QUANT_TBLS) do
|
||||
begin
|
||||
qtbl := cinfo^.quant_tbl_ptrs[i];
|
||||
if (qtbl <> NIL) then
|
||||
qtbl^.sent_table := suppress;
|
||||
end;
|
||||
|
||||
for i := 0 to pred(NUM_HUFF_TBLS) do
|
||||
begin
|
||||
htbl := cinfo^.dc_huff_tbl_ptrs[i];
|
||||
if (htbl <> NIL) then
|
||||
htbl^.sent_table := suppress;
|
||||
htbl := cinfo^.ac_huff_tbl_ptrs[i];
|
||||
if (htbl <> NIL) then
|
||||
htbl^.sent_table := suppress;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Finish JPEG compression.
|
||||
|
||||
If a multipass operating mode was selected, this may do a great deal of
|
||||
work including most of the actual output. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
||||
var
|
||||
iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state = CSTATE_SCANNING) or
|
||||
(cinfo^.global_state = CSTATE_RAW_OK) then
|
||||
begin
|
||||
{ Terminate first pass }
|
||||
if (cinfo^.next_scanline < cinfo^.image_height) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA);
|
||||
cinfo^.master^.finish_pass (cinfo);
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> CSTATE_WRCOEFS) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Perform any remaining passes }
|
||||
while (not cinfo^.master^.is_last_pass) do
|
||||
begin
|
||||
cinfo^.master^.prepare_for_pass (cinfo);
|
||||
for iMCU_row := 0 to pred(cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (iMCU_row);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.total_iMCU_rows);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
{ We bypass the main controller and invoke coef controller directly;
|
||||
all work is being done from the coefficient buffer. }
|
||||
|
||||
if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(NIL))) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND);
|
||||
end;
|
||||
cinfo^.master^.finish_pass (cinfo);
|
||||
end;
|
||||
{ Write EOI, do final cleanup }
|
||||
cinfo^.marker^.write_file_trailer (cinfo);
|
||||
cinfo^.dest^.term_destination (cinfo);
|
||||
{ We can use jpeg_abort to release memory and reset global_state }
|
||||
jpeg_abort(j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
|
||||
{ Write a special marker.
|
||||
This is only recommended for writing COM or APPn markers.
|
||||
Must be called after jpeg_start_compress() and before
|
||||
first call to jpeg_write_scanlines() or jpeg_write_raw_data(). }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
dataptr : JOCTETptr;
|
||||
datalen : uInt);
|
||||
var
|
||||
write_marker_byte : procedure(info : j_compress_ptr; val : int);
|
||||
begin
|
||||
if (cinfo^.next_scanline <> 0) or
|
||||
((cinfo^.global_state <> CSTATE_SCANNING) and
|
||||
(cinfo^.global_state <> CSTATE_RAW_OK) and
|
||||
(cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
cinfo^.marker^.write_marker_header (cinfo, marker, datalen);
|
||||
write_marker_byte := cinfo^.marker^.write_marker_byte; { copy for speed }
|
||||
while (datalen <> 0) do
|
||||
begin
|
||||
Dec(datalen);
|
||||
write_marker_byte (cinfo, dataptr^);
|
||||
Inc(dataptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Same, but piecemeal. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
||||
marker : int;
|
||||
datalen : uint);
|
||||
begin
|
||||
if (cinfo^.next_scanline <> 0) or
|
||||
((cinfo^.global_state <> CSTATE_SCANNING) and
|
||||
(cinfo^.global_state <> CSTATE_RAW_OK) and
|
||||
(cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
cinfo^.marker^.write_marker_header (cinfo, marker, datalen);
|
||||
end;
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
||||
begin
|
||||
cinfo^.marker^.write_marker_byte (cinfo, val);
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate compression function: just write an abbreviated table file.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
To produce a pair of files containing abbreviated tables and abbreviated
|
||||
image data, one would proceed as follows:
|
||||
|
||||
initialize JPEG object
|
||||
set JPEG parameters
|
||||
set destination to table file
|
||||
jpeg_write_tables(cinfo);
|
||||
set destination to image file
|
||||
jpeg_start_compress(cinfo, FALSE);
|
||||
write data...
|
||||
jpeg_finish_compress(cinfo);
|
||||
|
||||
jpeg_write_tables has the side effect of marking all tables written
|
||||
(same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
|
||||
will not re-emit the tables unless it is passed write_all_tables=TRUE. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_START) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
{ (Re)initialize error mgr and destination modules }
|
||||
cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo));
|
||||
cinfo^.dest^.init_destination (cinfo);
|
||||
{ Initialize the marker writer ... bit of a crock to do it here. }
|
||||
jinit_marker_writer(cinfo);
|
||||
{ Write them tables! }
|
||||
cinfo^.marker^.write_tables_only (cinfo);
|
||||
{ And clean up. }
|
||||
cinfo^.dest^.term_destination (cinfo);
|
||||
|
||||
{ In library releases up through v6a, we called jpeg_abort() here to free
|
||||
any working memory allocated by the destination manager and marker
|
||||
writer. Some applications had a problem with that: they allocated space
|
||||
of their own from the library memory manager, and didn't want it to go
|
||||
away during write_tables. So now we do nothing. This will cause a
|
||||
memory leak if an app calls write_tables repeatedly without doing a full
|
||||
compression cycle or otherwise resetting the JPEG object. However, that
|
||||
seems less bad than unexpectedly freeing memory in the normal case.
|
||||
An app that prefers the old behavior can call jpeg_abort for itself after
|
||||
each call to jpeg_write_tables(). }
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -1,222 +1,222 @@
|
||||
unit imjcapistd;
|
||||
|
||||
{ Original : jcapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
This file contains application interface code for the compression half
|
||||
of the JPEG library. These are the "standard" API routines that are
|
||||
used in the normal full-compression case. They are not used by a
|
||||
transcoding-only application. Note that if an application links in
|
||||
jpeg_start_compress, it will end up linking in the entire compressor.
|
||||
We thus must separate this file from jcapimin.c to avoid linking the
|
||||
whole compression library into a transcoder. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjcapimin, imjcinit;
|
||||
|
||||
|
||||
|
||||
{ Compression initialization.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
We require a write_all_tables parameter as a failsafe check when writing
|
||||
multiple datastreams from the same compression object. Since prior runs
|
||||
will have left all the tables marked sent_table=TRUE, a subsequent run
|
||||
would emit an abbreviated stream (no tables) by default. This may be what
|
||||
is wanted, but for safety's sake it should not be the default behavior:
|
||||
programmers should have to make a deliberate choice to emit abbreviated
|
||||
images. Therefore the documentation and examples should encourage people
|
||||
to pass write_all_tables=TRUE; then it will take active thought to do the
|
||||
wrong thing. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_start_compress (cinfo : j_compress_ptr;
|
||||
write_all_tables : boolean);
|
||||
|
||||
|
||||
{ Write some scanlines of data to the JPEG compressor.
|
||||
|
||||
The return value will be the number of lines actually written.
|
||||
This should be less than the supplied num_lines only in case that
|
||||
the data destination module has requested suspension of the compressor,
|
||||
or if more than image_height scanlines are passed in.
|
||||
|
||||
Note: we warn about excess calls to jpeg_write_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
excess scanlines passed in the last valid call are *silently* ignored,
|
||||
so that the application need not adjust num_lines for end-of-image
|
||||
when using a multiple-scanline buffer. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_scanlines (cinfo : j_compress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
{ Alternate entry point to write raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_raw_data (cinfo : j_compress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
implementation
|
||||
|
||||
{ Compression initialization.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
We require a write_all_tables parameter as a failsafe check when writing
|
||||
multiple datastreams from the same compression object. Since prior runs
|
||||
will have left all the tables marked sent_table=TRUE, a subsequent run
|
||||
would emit an abbreviated stream (no tables) by default. This may be what
|
||||
is wanted, but for safety's sake it should not be the default behavior:
|
||||
programmers should have to make a deliberate choice to emit abbreviated
|
||||
images. Therefore the documentation and examples should encourage people
|
||||
to pass write_all_tables=TRUE; then it will take active thought to do the
|
||||
wrong thing. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_start_compress (cinfo : j_compress_ptr;
|
||||
write_all_tables : boolean);
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_START) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
if (write_all_tables) then
|
||||
jpeg_suppress_tables(cinfo, FALSE); { mark all tables to be written }
|
||||
|
||||
{ (Re)initialize error mgr and destination modules }
|
||||
cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo));
|
||||
cinfo^.dest^.init_destination (cinfo);
|
||||
{ Perform master selection of active modules }
|
||||
jinit_compress_master(cinfo);
|
||||
{ Set up for the first pass }
|
||||
cinfo^.master^.prepare_for_pass (cinfo);
|
||||
{ Ready for application to drive first pass through jpeg_write_scanlines
|
||||
or jpeg_write_raw_data. }
|
||||
|
||||
cinfo^.next_scanline := 0;
|
||||
if cinfo^.raw_data_in then
|
||||
cinfo^.global_state := CSTATE_RAW_OK
|
||||
else
|
||||
cinfo^.global_state := CSTATE_SCANNING;
|
||||
end;
|
||||
|
||||
|
||||
{ Write some scanlines of data to the JPEG compressor.
|
||||
|
||||
The return value will be the number of lines actually written.
|
||||
This should be less than the supplied num_lines only in case that
|
||||
the data destination module has requested suspension of the compressor,
|
||||
or if more than image_height scanlines are passed in.
|
||||
|
||||
Note: we warn about excess calls to jpeg_write_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
excess scanlines passed in the last valid call are *silently* ignored,
|
||||
so that the application need not adjust num_lines for end-of-image
|
||||
when using a multiple-scanline buffer. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_scanlines (cinfo : j_compress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
row_ctr, rows_left : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_SCANNING) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.next_scanline >= cinfo^.image_height) then
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.next_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.image_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Give master control module another chance if this is first call to
|
||||
jpeg_write_scanlines. This lets output of the frame/scan headers be
|
||||
delayed so that application can write COM, etc, markers between
|
||||
jpeg_start_compress and jpeg_write_scanlines. }
|
||||
if (cinfo^.master^.call_pass_startup) then
|
||||
cinfo^.master^.pass_startup (cinfo);
|
||||
|
||||
{ Ignore any extra scanlines at bottom of image. }
|
||||
rows_left := cinfo^.image_height - cinfo^.next_scanline;
|
||||
if (num_lines > rows_left) then
|
||||
num_lines := rows_left;
|
||||
|
||||
row_ctr := 0;
|
||||
cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, num_lines);
|
||||
Inc(cinfo^.next_scanline, row_ctr);
|
||||
jpeg_write_scanlines := row_ctr;
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate entry point to write raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_raw_data (cinfo : j_compress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
lines_per_iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_RAW_OK) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.next_scanline >= cinfo^.image_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_write_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long(cinfo^.next_scanline);
|
||||
cinfo^.progress^.pass_limit := long(cinfo^.image_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Give master control module another chance if this is first call to
|
||||
jpeg_write_raw_data. This lets output of the frame/scan headers be
|
||||
delayed so that application can write COM, etc, markers between
|
||||
jpeg_start_compress and jpeg_write_raw_data. }
|
||||
|
||||
if (cinfo^.master^.call_pass_startup) then
|
||||
cinfo^.master^.pass_startup (cinfo);
|
||||
|
||||
{ Verify that at least one iMCU row has been passed. }
|
||||
lines_per_iMCU_row := cinfo^.max_v_samp_factor * DCTSIZE;
|
||||
if (num_lines < lines_per_iMCU_row) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE);
|
||||
|
||||
{ Directly compress the row. }
|
||||
if (not cinfo^.coef^.compress_data (cinfo, data)) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, suspend processing. }
|
||||
jpeg_write_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ OK, we processed one iMCU row. }
|
||||
Inc(cinfo^.next_scanline, lines_per_iMCU_row);
|
||||
jpeg_write_raw_data := lines_per_iMCU_row;
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcapistd;
|
||||
|
||||
{ Original : jcapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
This file contains application interface code for the compression half
|
||||
of the JPEG library. These are the "standard" API routines that are
|
||||
used in the normal full-compression case. They are not used by a
|
||||
transcoding-only application. Note that if an application links in
|
||||
jpeg_start_compress, it will end up linking in the entire compressor.
|
||||
We thus must separate this file from jcapimin.c to avoid linking the
|
||||
whole compression library into a transcoder. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjcapimin, imjcinit;
|
||||
|
||||
|
||||
|
||||
{ Compression initialization.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
We require a write_all_tables parameter as a failsafe check when writing
|
||||
multiple datastreams from the same compression object. Since prior runs
|
||||
will have left all the tables marked sent_table=TRUE, a subsequent run
|
||||
would emit an abbreviated stream (no tables) by default. This may be what
|
||||
is wanted, but for safety's sake it should not be the default behavior:
|
||||
programmers should have to make a deliberate choice to emit abbreviated
|
||||
images. Therefore the documentation and examples should encourage people
|
||||
to pass write_all_tables=TRUE; then it will take active thought to do the
|
||||
wrong thing. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_start_compress (cinfo : j_compress_ptr;
|
||||
write_all_tables : boolean);
|
||||
|
||||
|
||||
{ Write some scanlines of data to the JPEG compressor.
|
||||
|
||||
The return value will be the number of lines actually written.
|
||||
This should be less than the supplied num_lines only in case that
|
||||
the data destination module has requested suspension of the compressor,
|
||||
or if more than image_height scanlines are passed in.
|
||||
|
||||
Note: we warn about excess calls to jpeg_write_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
excess scanlines passed in the last valid call are *silently* ignored,
|
||||
so that the application need not adjust num_lines for end-of-image
|
||||
when using a multiple-scanline buffer. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_scanlines (cinfo : j_compress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
{ Alternate entry point to write raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_raw_data (cinfo : j_compress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
implementation
|
||||
|
||||
{ Compression initialization.
|
||||
Before calling this, all parameters and a data destination must be set up.
|
||||
|
||||
We require a write_all_tables parameter as a failsafe check when writing
|
||||
multiple datastreams from the same compression object. Since prior runs
|
||||
will have left all the tables marked sent_table=TRUE, a subsequent run
|
||||
would emit an abbreviated stream (no tables) by default. This may be what
|
||||
is wanted, but for safety's sake it should not be the default behavior:
|
||||
programmers should have to make a deliberate choice to emit abbreviated
|
||||
images. Therefore the documentation and examples should encourage people
|
||||
to pass write_all_tables=TRUE; then it will take active thought to do the
|
||||
wrong thing. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_start_compress (cinfo : j_compress_ptr;
|
||||
write_all_tables : boolean);
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_START) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
|
||||
if (write_all_tables) then
|
||||
jpeg_suppress_tables(cinfo, FALSE); { mark all tables to be written }
|
||||
|
||||
{ (Re)initialize error mgr and destination modules }
|
||||
cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo));
|
||||
cinfo^.dest^.init_destination (cinfo);
|
||||
{ Perform master selection of active modules }
|
||||
jinit_compress_master(cinfo);
|
||||
{ Set up for the first pass }
|
||||
cinfo^.master^.prepare_for_pass (cinfo);
|
||||
{ Ready for application to drive first pass through jpeg_write_scanlines
|
||||
or jpeg_write_raw_data. }
|
||||
|
||||
cinfo^.next_scanline := 0;
|
||||
if cinfo^.raw_data_in then
|
||||
cinfo^.global_state := CSTATE_RAW_OK
|
||||
else
|
||||
cinfo^.global_state := CSTATE_SCANNING;
|
||||
end;
|
||||
|
||||
|
||||
{ Write some scanlines of data to the JPEG compressor.
|
||||
|
||||
The return value will be the number of lines actually written.
|
||||
This should be less than the supplied num_lines only in case that
|
||||
the data destination module has requested suspension of the compressor,
|
||||
or if more than image_height scanlines are passed in.
|
||||
|
||||
Note: we warn about excess calls to jpeg_write_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
excess scanlines passed in the last valid call are *silently* ignored,
|
||||
so that the application need not adjust num_lines for end-of-image
|
||||
when using a multiple-scanline buffer. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_scanlines (cinfo : j_compress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
row_ctr, rows_left : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_SCANNING) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.next_scanline >= cinfo^.image_height) then
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.next_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.image_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Give master control module another chance if this is first call to
|
||||
jpeg_write_scanlines. This lets output of the frame/scan headers be
|
||||
delayed so that application can write COM, etc, markers between
|
||||
jpeg_start_compress and jpeg_write_scanlines. }
|
||||
if (cinfo^.master^.call_pass_startup) then
|
||||
cinfo^.master^.pass_startup (cinfo);
|
||||
|
||||
{ Ignore any extra scanlines at bottom of image. }
|
||||
rows_left := cinfo^.image_height - cinfo^.next_scanline;
|
||||
if (num_lines > rows_left) then
|
||||
num_lines := rows_left;
|
||||
|
||||
row_ctr := 0;
|
||||
cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, num_lines);
|
||||
Inc(cinfo^.next_scanline, row_ctr);
|
||||
jpeg_write_scanlines := row_ctr;
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate entry point to write raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_write_raw_data (cinfo : j_compress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
num_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
lines_per_iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> CSTATE_RAW_OK) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.next_scanline >= cinfo^.image_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_write_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long(cinfo^.next_scanline);
|
||||
cinfo^.progress^.pass_limit := long(cinfo^.image_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Give master control module another chance if this is first call to
|
||||
jpeg_write_raw_data. This lets output of the frame/scan headers be
|
||||
delayed so that application can write COM, etc, markers between
|
||||
jpeg_start_compress and jpeg_write_raw_data. }
|
||||
|
||||
if (cinfo^.master^.call_pass_startup) then
|
||||
cinfo^.master^.pass_startup (cinfo);
|
||||
|
||||
{ Verify that at least one iMCU row has been passed. }
|
||||
lines_per_iMCU_row := cinfo^.max_v_samp_factor * DCTSIZE;
|
||||
if (num_lines < lines_per_iMCU_row) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE);
|
||||
|
||||
{ Directly compress the row. }
|
||||
if (not cinfo^.coef^.compress_data (cinfo, data)) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, suspend processing. }
|
||||
jpeg_write_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ OK, we processed one iMCU row. }
|
||||
Inc(cinfo^.next_scanline, lines_per_iMCU_row);
|
||||
jpeg_write_raw_data := lines_per_iMCU_row;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,95 +1,95 @@
|
||||
unit imjcinit;
|
||||
|
||||
{ Original: jcinit.c ; Copyright (C) 1991-1997, Thomas G. Lane. }
|
||||
|
||||
{ This file contains initialization logic for the JPEG compressor.
|
||||
This routine is in charge of selecting the modules to be executed and
|
||||
making an initialization call to each one.
|
||||
|
||||
Logically, this code belongs in jcmaster.c. It's split out because
|
||||
linking this routine implies linking the entire compression library.
|
||||
For a transcoding-only application, we want to be able to use jcmaster.c
|
||||
without linking in the whole library. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
{$ifdef C_PROGRESSIVE_SUPPORTED}
|
||||
imjcphuff,
|
||||
{$endif}
|
||||
imjchuff, imjcmaster, imjccolor, imjcsample, imjcprepct,
|
||||
imjcdctmgr, imjccoefct, imjcmainct, imjcmarker;
|
||||
|
||||
{ Master selection of compression modules.
|
||||
This is done once at the start of processing an image. We determine
|
||||
which modules will be used and give them appropriate initialization calls. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_compress_master (cinfo : j_compress_ptr);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
{ Master selection of compression modules.
|
||||
This is done once at the start of processing an image. We determine
|
||||
which modules will be used and give them appropriate initialization calls. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_compress_master (cinfo : j_compress_ptr);
|
||||
begin
|
||||
{ Initialize master control (includes parameter checking/processing) }
|
||||
jinit_c_master_control(cinfo, FALSE { full compression });
|
||||
|
||||
{ Preprocessing }
|
||||
if (not cinfo^.raw_data_in) then
|
||||
begin
|
||||
jinit_color_converter(cinfo);
|
||||
jinit_downsampler(cinfo);
|
||||
jinit_c_prep_controller(cinfo, FALSE { never need full buffer here });
|
||||
end;
|
||||
{ Forward DCT }
|
||||
jinit_forward_dct(cinfo);
|
||||
{ Entropy encoding: either Huffman or arithmetic coding. }
|
||||
if (cinfo^.arith_code) then
|
||||
begin
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_ARITH_NOTIMPL);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (cinfo^.progressive_mode) then
|
||||
begin
|
||||
{$ifdef C_PROGRESSIVE_SUPPORTED}
|
||||
jinit_phuff_encoder(cinfo);
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
jinit_huff_encoder(cinfo);
|
||||
end;
|
||||
|
||||
{ Need a full-image coefficient buffer in any multi-pass mode. }
|
||||
jinit_c_coef_controller(cinfo,
|
||||
(cinfo^.num_scans > 1) or (cinfo^.optimize_coding));
|
||||
jinit_c_main_controller(cinfo, FALSE { never need full buffer here });
|
||||
|
||||
jinit_marker_writer(cinfo);
|
||||
|
||||
{ We can now tell the memory manager to allocate virtual arrays. }
|
||||
cinfo^.mem^.realize_virt_arrays (j_common_ptr(cinfo));
|
||||
|
||||
{ Write the datastream header (SOI) immediately.
|
||||
Frame and scan headers are postponed till later.
|
||||
This lets application insert special markers after the SOI. }
|
||||
|
||||
cinfo^.marker^.write_file_header (cinfo);
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcinit;
|
||||
|
||||
{ Original: jcinit.c ; Copyright (C) 1991-1997, Thomas G. Lane. }
|
||||
|
||||
{ This file contains initialization logic for the JPEG compressor.
|
||||
This routine is in charge of selecting the modules to be executed and
|
||||
making an initialization call to each one.
|
||||
|
||||
Logically, this code belongs in jcmaster.c. It's split out because
|
||||
linking this routine implies linking the entire compression library.
|
||||
For a transcoding-only application, we want to be able to use jcmaster.c
|
||||
without linking in the whole library. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
{$ifdef C_PROGRESSIVE_SUPPORTED}
|
||||
imjcphuff,
|
||||
{$endif}
|
||||
imjchuff, imjcmaster, imjccolor, imjcsample, imjcprepct,
|
||||
imjcdctmgr, imjccoefct, imjcmainct, imjcmarker;
|
||||
|
||||
{ Master selection of compression modules.
|
||||
This is done once at the start of processing an image. We determine
|
||||
which modules will be used and give them appropriate initialization calls. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_compress_master (cinfo : j_compress_ptr);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
{ Master selection of compression modules.
|
||||
This is done once at the start of processing an image. We determine
|
||||
which modules will be used and give them appropriate initialization calls. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_compress_master (cinfo : j_compress_ptr);
|
||||
begin
|
||||
{ Initialize master control (includes parameter checking/processing) }
|
||||
jinit_c_master_control(cinfo, FALSE { full compression });
|
||||
|
||||
{ Preprocessing }
|
||||
if (not cinfo^.raw_data_in) then
|
||||
begin
|
||||
jinit_color_converter(cinfo);
|
||||
jinit_downsampler(cinfo);
|
||||
jinit_c_prep_controller(cinfo, FALSE { never need full buffer here });
|
||||
end;
|
||||
{ Forward DCT }
|
||||
jinit_forward_dct(cinfo);
|
||||
{ Entropy encoding: either Huffman or arithmetic coding. }
|
||||
if (cinfo^.arith_code) then
|
||||
begin
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_ARITH_NOTIMPL);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (cinfo^.progressive_mode) then
|
||||
begin
|
||||
{$ifdef C_PROGRESSIVE_SUPPORTED}
|
||||
jinit_phuff_encoder(cinfo);
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
jinit_huff_encoder(cinfo);
|
||||
end;
|
||||
|
||||
{ Need a full-image coefficient buffer in any multi-pass mode. }
|
||||
jinit_c_coef_controller(cinfo,
|
||||
(cinfo^.num_scans > 1) or (cinfo^.optimize_coding));
|
||||
jinit_c_main_controller(cinfo, FALSE { never need full buffer here });
|
||||
|
||||
jinit_marker_writer(cinfo);
|
||||
|
||||
{ We can now tell the memory manager to allocate virtual arrays. }
|
||||
cinfo^.mem^.realize_virt_arrays (j_common_ptr(cinfo));
|
||||
|
||||
{ Write the datastream header (SOI) immediately.
|
||||
Frame and scan headers are postponed till later.
|
||||
This lets application insert special markers after the SOI. }
|
||||
|
||||
cinfo^.marker^.write_file_header (cinfo);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -1,343 +1,343 @@
|
||||
unit imjcmainct;
|
||||
|
||||
{ This file contains the main buffer controller for compression.
|
||||
The main buffer lies between the pre-processor and the JPEG
|
||||
compressor proper; it holds downsampled data in the JPEG colorspace. }
|
||||
|
||||
{ Original : jcmainct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
{ Note: currently, there is no operating mode in which a full-image buffer
|
||||
is needed at this step. If there were, that mode could not be used with
|
||||
"raw data" input, since this module is bypassed in that case. However,
|
||||
we've left the code here for possible use in special applications. }
|
||||
|
||||
{$undef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
imjutils,
|
||||
{$endif}
|
||||
imjpeglib;
|
||||
|
||||
{ Initialize main buffer controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_main_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{ Private buffer controller object }
|
||||
|
||||
type
|
||||
my_main_ptr = ^my_main_controller;
|
||||
my_main_controller = record
|
||||
pub : jpeg_c_main_controller; { public fields }
|
||||
|
||||
cur_iMCU_row : JDIMENSION; { number of current iMCU row }
|
||||
rowgroup_ctr : JDIMENSION; { counts row groups received in iMCU row }
|
||||
suspended : boolean; { remember if we suspended output }
|
||||
pass_mode : J_BUF_MODE; { current operating mode }
|
||||
|
||||
{ If using just a strip buffer, this points to the entire set of buffers
|
||||
(we allocate one for each component). In the full-image case, this
|
||||
points to the currently accessible strips of the virtual arrays. }
|
||||
|
||||
buffer : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{ If using full-image storage, this array holds pointers to virtual-array
|
||||
control blocks for each component. Unused if not full-image storage. }
|
||||
|
||||
whole_image : array[0..MAX_COMPONENTS-1] of jvirt_sarray_ptr;
|
||||
{$endif}
|
||||
end; {my_main_controller}
|
||||
|
||||
|
||||
{ Forward declarations }
|
||||
{METHODDEF}
|
||||
procedure process_data_simple_main(cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr: JDIMENSION;
|
||||
in_rows_avail : JDIMENSION); forward;
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{METHODDEF}
|
||||
procedure process_data_buffer_main(cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION); forward;
|
||||
{$endif}
|
||||
|
||||
|
||||
{ Initialize for a processing pass. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass_main (cinfo : j_compress_ptr;
|
||||
pass_mode : J_BUF_MODE);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
|
||||
{ Do nothing in raw-data mode. }
|
||||
if (cinfo^.raw_data_in) then
|
||||
exit;
|
||||
|
||||
main^.cur_iMCU_row := 0; { initialize counters }
|
||||
main^.rowgroup_ctr := 0;
|
||||
main^.suspended := FALSE;
|
||||
main^.pass_mode := pass_mode; { save mode for use by process_data }
|
||||
|
||||
case (pass_mode) of
|
||||
JBUF_PASS_THRU:
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
if (main^.whole_image[0] <> NIL) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
{$endif}
|
||||
main^.pub.process_data := process_data_simple_main;
|
||||
end;
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
JBUF_SAVE_SOURCE,
|
||||
JBUF_CRANK_DEST,
|
||||
JBUF_SAVE_AND_PASS:
|
||||
begin
|
||||
if (main^.whole_image[0] = NIL) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
main^.pub.process_data := process_data_buffer_main;
|
||||
end;
|
||||
{$endif}
|
||||
else
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Process some data.
|
||||
This routine handles the simple pass-through mode,
|
||||
where we have only a strip buffer. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure process_data_simple_main (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
|
||||
while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
{ Read input data if we haven't filled the main buffer yet }
|
||||
if (main^.rowgroup_ctr < DCTSIZE) then
|
||||
cinfo^.prep^.pre_process_data (cinfo,
|
||||
input_buf,
|
||||
in_row_ctr,
|
||||
in_rows_avail,
|
||||
JSAMPIMAGE(@main^.buffer),
|
||||
main^.rowgroup_ctr,
|
||||
JDIMENSION(DCTSIZE));
|
||||
|
||||
{ If we don't have a full iMCU row buffered, return to application for
|
||||
more data. Note that preprocessor will always pad to fill the iMCU row
|
||||
at the bottom of the image. }
|
||||
if (main^.rowgroup_ctr <> DCTSIZE) then
|
||||
exit;
|
||||
|
||||
{ Send the completed row to the compressor }
|
||||
if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(@main^.buffer))) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, then we must need to
|
||||
suspend processing and return to the application. In this situation
|
||||
we pretend we didn't yet consume the last input row; otherwise, if
|
||||
it happened to be the last row of the image, the application would
|
||||
think we were done. }
|
||||
|
||||
if (not main^.suspended) then
|
||||
begin
|
||||
Dec(in_row_ctr);
|
||||
main^.suspended := TRUE;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
{ We did finish the row. Undo our little suspension hack if a previous
|
||||
call suspended; then mark the main buffer empty. }
|
||||
|
||||
if (main^.suspended) then
|
||||
begin
|
||||
Inc(in_row_ctr);
|
||||
main^.suspended := FALSE;
|
||||
end;
|
||||
main^.rowgroup_ctr := 0;
|
||||
Inc(main^.cur_iMCU_row);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
{ Process some data.
|
||||
This routine handles all of the modes that use a full-size buffer. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure process_data_buffer_main (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
writing : boolean;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
writing := (main^.pass_mode <> JBUF_CRANK_DEST);
|
||||
|
||||
while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
{ Realign the virtual buffers if at the start of an iMCU row. }
|
||||
if (main^.rowgroup_ctr = 0) then
|
||||
begin
|
||||
compptr := cinfo^.comp_info;
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.buffer[ci] := cinfo^.mem^.access_virt_sarray
|
||||
(j_common_ptr (cinfo), main^.whole_image[ci],
|
||||
main^.cur_iMCU_row * (compptr^.v_samp_factor * DCTSIZE),
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE), writing);
|
||||
Inc(compptr);
|
||||
end;
|
||||
{ In a read pass, pretend we just read some source data. }
|
||||
if (not writing) then
|
||||
begin
|
||||
Inc(in_row_ctr, cinfo^.max_v_samp_factor * DCTSIZE);
|
||||
main^.rowgroup_ctr := DCTSIZE;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ If a write pass, read input data until the current iMCU row is full. }
|
||||
{ Note: preprocessor will pad if necessary to fill the last iMCU row. }
|
||||
if (writing) then
|
||||
begin
|
||||
cinfo^.prep^.pre_process_data (cinfo,
|
||||
input_buf, in_row_ctr, in_rows_avail,
|
||||
JSAMPIMAGE(@main^.buffer),
|
||||
main^.rowgroup_ctr,
|
||||
JDIMENSION (DCTSIZE));
|
||||
|
||||
{ Return to application if we need more data to fill the iMCU row. }
|
||||
if (main^.rowgroup_ctr < DCTSIZE) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Emit data, unless this is a sink-only pass. }
|
||||
if (main^.pass_mode <> JBUF_SAVE_SOURCE) then
|
||||
begin
|
||||
if (not cinfo^.coef^.compress_data (cinfo,
|
||||
JSAMPIMAGE(@main^.buffer))) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, then we must need to
|
||||
suspend processing and return to the application. In this situation
|
||||
we pretend we didn't yet consume the last input row; otherwise, if
|
||||
it happened to be the last row of the image, the application would
|
||||
think we were done. }
|
||||
|
||||
if (not main^.suspended) then
|
||||
begin
|
||||
Dec(in_row_ctr);
|
||||
main^.suspended := TRUE;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
{ We did finish the row. Undo our little suspension hack if a previous
|
||||
call suspended; then mark the main buffer empty. }
|
||||
|
||||
if (main^.suspended) then
|
||||
begin
|
||||
Inc(in_row_ctr);
|
||||
main^.suspended := FALSE;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ If get here, we are done with this iMCU row. Mark buffer empty. }
|
||||
main^.rowgroup_ctr := 0;
|
||||
Inc(main^.cur_iMCU_row);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$endif} { FULL_MAIN_BUFFER_SUPPORTED }
|
||||
|
||||
|
||||
{ Initialize main buffer controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_main_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
begin
|
||||
main := my_main_ptr(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(my_main_controller)) );
|
||||
cinfo^.main := jpeg_c_main_controller_ptr(main);
|
||||
main^.pub.start_pass := start_pass_main;
|
||||
|
||||
{ We don't need to create a buffer in raw-data mode. }
|
||||
if (cinfo^.raw_data_in) then
|
||||
exit;
|
||||
|
||||
{ Create the buffer. It holds downsampled data, so each component
|
||||
may be of a different size. }
|
||||
|
||||
if (need_full_buffer) then
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{ Allocate a full-image virtual array for each component }
|
||||
{ Note we pad the bottom to a multiple of the iMCU height }
|
||||
compptr := cinfo^.comp_info;
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.whole_image[ci] := cinfo^.mem^.request_virt_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
JDIMENSION (jround_up( long (compptr^.height_in_blocks),
|
||||
long (compptr^.v_samp_factor)) * DCTSIZE),
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
|
||||
Inc(compptr);
|
||||
end;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
main^.whole_image[0] := NIL; { flag for no virtual arrays }
|
||||
{$endif}
|
||||
{ Allocate a strip buffer for each component }
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.buffer[ci] := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcmainct;
|
||||
|
||||
{ This file contains the main buffer controller for compression.
|
||||
The main buffer lies between the pre-processor and the JPEG
|
||||
compressor proper; it holds downsampled data in the JPEG colorspace. }
|
||||
|
||||
{ Original : jcmainct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
{ Note: currently, there is no operating mode in which a full-image buffer
|
||||
is needed at this step. If there were, that mode could not be used with
|
||||
"raw data" input, since this module is bypassed in that case. However,
|
||||
we've left the code here for possible use in special applications. }
|
||||
|
||||
{$undef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
imjutils,
|
||||
{$endif}
|
||||
imjpeglib;
|
||||
|
||||
{ Initialize main buffer controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_main_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{ Private buffer controller object }
|
||||
|
||||
type
|
||||
my_main_ptr = ^my_main_controller;
|
||||
my_main_controller = record
|
||||
pub : jpeg_c_main_controller; { public fields }
|
||||
|
||||
cur_iMCU_row : JDIMENSION; { number of current iMCU row }
|
||||
rowgroup_ctr : JDIMENSION; { counts row groups received in iMCU row }
|
||||
suspended : boolean; { remember if we suspended output }
|
||||
pass_mode : J_BUF_MODE; { current operating mode }
|
||||
|
||||
{ If using just a strip buffer, this points to the entire set of buffers
|
||||
(we allocate one for each component). In the full-image case, this
|
||||
points to the currently accessible strips of the virtual arrays. }
|
||||
|
||||
buffer : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{ If using full-image storage, this array holds pointers to virtual-array
|
||||
control blocks for each component. Unused if not full-image storage. }
|
||||
|
||||
whole_image : array[0..MAX_COMPONENTS-1] of jvirt_sarray_ptr;
|
||||
{$endif}
|
||||
end; {my_main_controller}
|
||||
|
||||
|
||||
{ Forward declarations }
|
||||
{METHODDEF}
|
||||
procedure process_data_simple_main(cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr: JDIMENSION;
|
||||
in_rows_avail : JDIMENSION); forward;
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{METHODDEF}
|
||||
procedure process_data_buffer_main(cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION); forward;
|
||||
{$endif}
|
||||
|
||||
|
||||
{ Initialize for a processing pass. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass_main (cinfo : j_compress_ptr;
|
||||
pass_mode : J_BUF_MODE);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
|
||||
{ Do nothing in raw-data mode. }
|
||||
if (cinfo^.raw_data_in) then
|
||||
exit;
|
||||
|
||||
main^.cur_iMCU_row := 0; { initialize counters }
|
||||
main^.rowgroup_ctr := 0;
|
||||
main^.suspended := FALSE;
|
||||
main^.pass_mode := pass_mode; { save mode for use by process_data }
|
||||
|
||||
case (pass_mode) of
|
||||
JBUF_PASS_THRU:
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
if (main^.whole_image[0] <> NIL) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
{$endif}
|
||||
main^.pub.process_data := process_data_simple_main;
|
||||
end;
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
JBUF_SAVE_SOURCE,
|
||||
JBUF_CRANK_DEST,
|
||||
JBUF_SAVE_AND_PASS:
|
||||
begin
|
||||
if (main^.whole_image[0] = NIL) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
main^.pub.process_data := process_data_buffer_main;
|
||||
end;
|
||||
{$endif}
|
||||
else
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Process some data.
|
||||
This routine handles the simple pass-through mode,
|
||||
where we have only a strip buffer. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure process_data_simple_main (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
|
||||
while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
{ Read input data if we haven't filled the main buffer yet }
|
||||
if (main^.rowgroup_ctr < DCTSIZE) then
|
||||
cinfo^.prep^.pre_process_data (cinfo,
|
||||
input_buf,
|
||||
in_row_ctr,
|
||||
in_rows_avail,
|
||||
JSAMPIMAGE(@main^.buffer),
|
||||
main^.rowgroup_ctr,
|
||||
JDIMENSION(DCTSIZE));
|
||||
|
||||
{ If we don't have a full iMCU row buffered, return to application for
|
||||
more data. Note that preprocessor will always pad to fill the iMCU row
|
||||
at the bottom of the image. }
|
||||
if (main^.rowgroup_ctr <> DCTSIZE) then
|
||||
exit;
|
||||
|
||||
{ Send the completed row to the compressor }
|
||||
if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(@main^.buffer))) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, then we must need to
|
||||
suspend processing and return to the application. In this situation
|
||||
we pretend we didn't yet consume the last input row; otherwise, if
|
||||
it happened to be the last row of the image, the application would
|
||||
think we were done. }
|
||||
|
||||
if (not main^.suspended) then
|
||||
begin
|
||||
Dec(in_row_ctr);
|
||||
main^.suspended := TRUE;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
{ We did finish the row. Undo our little suspension hack if a previous
|
||||
call suspended; then mark the main buffer empty. }
|
||||
|
||||
if (main^.suspended) then
|
||||
begin
|
||||
Inc(in_row_ctr);
|
||||
main^.suspended := FALSE;
|
||||
end;
|
||||
main^.rowgroup_ctr := 0;
|
||||
Inc(main^.cur_iMCU_row);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
{ Process some data.
|
||||
This routine handles all of the modes that use a full-size buffer. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure process_data_buffer_main (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
writing : boolean;
|
||||
begin
|
||||
main := my_main_ptr (cinfo^.main);
|
||||
writing := (main^.pass_mode <> JBUF_CRANK_DEST);
|
||||
|
||||
while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
|
||||
begin
|
||||
{ Realign the virtual buffers if at the start of an iMCU row. }
|
||||
if (main^.rowgroup_ctr = 0) then
|
||||
begin
|
||||
compptr := cinfo^.comp_info;
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.buffer[ci] := cinfo^.mem^.access_virt_sarray
|
||||
(j_common_ptr (cinfo), main^.whole_image[ci],
|
||||
main^.cur_iMCU_row * (compptr^.v_samp_factor * DCTSIZE),
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE), writing);
|
||||
Inc(compptr);
|
||||
end;
|
||||
{ In a read pass, pretend we just read some source data. }
|
||||
if (not writing) then
|
||||
begin
|
||||
Inc(in_row_ctr, cinfo^.max_v_samp_factor * DCTSIZE);
|
||||
main^.rowgroup_ctr := DCTSIZE;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ If a write pass, read input data until the current iMCU row is full. }
|
||||
{ Note: preprocessor will pad if necessary to fill the last iMCU row. }
|
||||
if (writing) then
|
||||
begin
|
||||
cinfo^.prep^.pre_process_data (cinfo,
|
||||
input_buf, in_row_ctr, in_rows_avail,
|
||||
JSAMPIMAGE(@main^.buffer),
|
||||
main^.rowgroup_ctr,
|
||||
JDIMENSION (DCTSIZE));
|
||||
|
||||
{ Return to application if we need more data to fill the iMCU row. }
|
||||
if (main^.rowgroup_ctr < DCTSIZE) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Emit data, unless this is a sink-only pass. }
|
||||
if (main^.pass_mode <> JBUF_SAVE_SOURCE) then
|
||||
begin
|
||||
if (not cinfo^.coef^.compress_data (cinfo,
|
||||
JSAMPIMAGE(@main^.buffer))) then
|
||||
begin
|
||||
{ If compressor did not consume the whole row, then we must need to
|
||||
suspend processing and return to the application. In this situation
|
||||
we pretend we didn't yet consume the last input row; otherwise, if
|
||||
it happened to be the last row of the image, the application would
|
||||
think we were done. }
|
||||
|
||||
if (not main^.suspended) then
|
||||
begin
|
||||
Dec(in_row_ctr);
|
||||
main^.suspended := TRUE;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
{ We did finish the row. Undo our little suspension hack if a previous
|
||||
call suspended; then mark the main buffer empty. }
|
||||
|
||||
if (main^.suspended) then
|
||||
begin
|
||||
Inc(in_row_ctr);
|
||||
main^.suspended := FALSE;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ If get here, we are done with this iMCU row. Mark buffer empty. }
|
||||
main^.rowgroup_ctr := 0;
|
||||
Inc(main^.cur_iMCU_row);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$endif} { FULL_MAIN_BUFFER_SUPPORTED }
|
||||
|
||||
|
||||
{ Initialize main buffer controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_main_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
var
|
||||
main : my_main_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
begin
|
||||
main := my_main_ptr(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(my_main_controller)) );
|
||||
cinfo^.main := jpeg_c_main_controller_ptr(main);
|
||||
main^.pub.start_pass := start_pass_main;
|
||||
|
||||
{ We don't need to create a buffer in raw-data mode. }
|
||||
if (cinfo^.raw_data_in) then
|
||||
exit;
|
||||
|
||||
{ Create the buffer. It holds downsampled data, so each component
|
||||
may be of a different size. }
|
||||
|
||||
if (need_full_buffer) then
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
{ Allocate a full-image virtual array for each component }
|
||||
{ Note we pad the bottom to a multiple of the iMCU height }
|
||||
compptr := cinfo^.comp_info;
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.whole_image[ci] := cinfo^.mem^.request_virt_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
JDIMENSION (jround_up( long (compptr^.height_in_blocks),
|
||||
long (compptr^.v_samp_factor)) * DCTSIZE),
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
|
||||
Inc(compptr);
|
||||
end;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{$ifdef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
main^.whole_image[0] := NIL; { flag for no virtual arrays }
|
||||
{$endif}
|
||||
{ Allocate a strip buffer for each component }
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
main^.buffer[ci] := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,130 +1,130 @@
|
||||
unit imjcomapi;
|
||||
|
||||
{ This file contains application interface routines that are used for both
|
||||
compression and decompression. }
|
||||
|
||||
{ Original: jcomapi.c; Copyright (C) 1994-1997, Thomas G. Lane. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjpeglib;
|
||||
|
||||
{ Abort processing of a JPEG compression or decompression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort (cinfo : j_common_ptr);
|
||||
|
||||
|
||||
{ Destruction of a JPEG object. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy (cinfo : j_common_ptr);
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR;
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR;
|
||||
|
||||
implementation
|
||||
|
||||
{ Abort processing of a JPEG compression or decompression operation,
|
||||
but don't destroy the object itself.
|
||||
|
||||
For this, we merely clean up all the nonpermanent memory pools.
|
||||
Note that temp files (virtual arrays) are not allowed to belong to
|
||||
the permanent pool, so we will be able to close all temp files here.
|
||||
Closing a data source or destination, if necessary, is the application's
|
||||
responsibility. }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort (cinfo : j_common_ptr);
|
||||
var
|
||||
pool : int;
|
||||
begin
|
||||
{ Do nothing if called on a not-initialized or destroyed JPEG object. }
|
||||
if (cinfo^.mem = NIL) then
|
||||
exit;
|
||||
|
||||
{ Releasing pools in reverse order might help avoid fragmentation
|
||||
with some (brain-damaged) malloc libraries. }
|
||||
|
||||
for pool := JPOOL_NUMPOOLS-1 downto JPOOL_PERMANENT+1 do
|
||||
begin
|
||||
cinfo^.mem^.free_pool (cinfo, pool);
|
||||
end;
|
||||
|
||||
{ Reset overall state for possible reuse of object }
|
||||
if (cinfo^.is_decompressor) then
|
||||
begin
|
||||
cinfo^.global_state := DSTATE_START;
|
||||
{ Try to keep application from accessing now-deleted marker list.
|
||||
A bit kludgy to do it here, but this is the most central place. }
|
||||
j_decompress_ptr(cinfo)^.marker_list := NIL;
|
||||
end
|
||||
else
|
||||
begin
|
||||
cinfo^.global_state := CSTATE_START;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Destruction of a JPEG object.
|
||||
|
||||
Everything gets deallocated except the master jpeg_compress_struct itself
|
||||
and the error manager struct. Both of these are supplied by the application
|
||||
and must be freed, if necessary, by the application. (Often they are on
|
||||
the stack and so don't need to be freed anyway.)
|
||||
Closing a data source or destination, if necessary, is the application's
|
||||
responsibility. }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy (cinfo : j_common_ptr);
|
||||
begin
|
||||
{ We need only tell the memory manager to release everything. }
|
||||
{ NB: mem pointer is NIL if memory mgr failed to initialize. }
|
||||
if (cinfo^.mem <> NIL) then
|
||||
cinfo^.mem^.self_destruct (cinfo);
|
||||
cinfo^.mem := NIL; { be safe if jpeg_destroy is called twice }
|
||||
cinfo^.global_state := 0; { mark it destroyed }
|
||||
end;
|
||||
|
||||
|
||||
{ Convenience routines for allocating quantization and Huffman tables.
|
||||
(Would jutils.c be a more reasonable place to put these?) }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR;
|
||||
var
|
||||
tbl : JQUANT_TBL_PTR;
|
||||
begin
|
||||
tbl := JQUANT_TBL_PTR(
|
||||
cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL))
|
||||
);
|
||||
tbl^.sent_table := FALSE; { make sure this is false in any new table }
|
||||
jpeg_alloc_quant_table := tbl;
|
||||
end;
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR;
|
||||
var
|
||||
tbl : JHUFF_TBL_PTR;
|
||||
begin
|
||||
tbl := JHUFF_TBL_PTR(
|
||||
cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL))
|
||||
);
|
||||
tbl^.sent_table := FALSE; { make sure this is false in any new table }
|
||||
jpeg_alloc_huff_table := tbl;
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcomapi;
|
||||
|
||||
{ This file contains application interface routines that are used for both
|
||||
compression and decompression. }
|
||||
|
||||
{ Original: jcomapi.c; Copyright (C) 1994-1997, Thomas G. Lane. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjpeglib;
|
||||
|
||||
{ Abort processing of a JPEG compression or decompression operation,
|
||||
but don't destroy the object itself. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort (cinfo : j_common_ptr);
|
||||
|
||||
|
||||
{ Destruction of a JPEG object. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy (cinfo : j_common_ptr);
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR;
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR;
|
||||
|
||||
implementation
|
||||
|
||||
{ Abort processing of a JPEG compression or decompression operation,
|
||||
but don't destroy the object itself.
|
||||
|
||||
For this, we merely clean up all the nonpermanent memory pools.
|
||||
Note that temp files (virtual arrays) are not allowed to belong to
|
||||
the permanent pool, so we will be able to close all temp files here.
|
||||
Closing a data source or destination, if necessary, is the application's
|
||||
responsibility. }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_abort (cinfo : j_common_ptr);
|
||||
var
|
||||
pool : int;
|
||||
begin
|
||||
{ Do nothing if called on a not-initialized or destroyed JPEG object. }
|
||||
if (cinfo^.mem = NIL) then
|
||||
exit;
|
||||
|
||||
{ Releasing pools in reverse order might help avoid fragmentation
|
||||
with some (brain-damaged) malloc libraries. }
|
||||
|
||||
for pool := JPOOL_NUMPOOLS-1 downto JPOOL_PERMANENT+1 do
|
||||
begin
|
||||
cinfo^.mem^.free_pool (cinfo, pool);
|
||||
end;
|
||||
|
||||
{ Reset overall state for possible reuse of object }
|
||||
if (cinfo^.is_decompressor) then
|
||||
begin
|
||||
cinfo^.global_state := DSTATE_START;
|
||||
{ Try to keep application from accessing now-deleted marker list.
|
||||
A bit kludgy to do it here, but this is the most central place. }
|
||||
j_decompress_ptr(cinfo)^.marker_list := NIL;
|
||||
end
|
||||
else
|
||||
begin
|
||||
cinfo^.global_state := CSTATE_START;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Destruction of a JPEG object.
|
||||
|
||||
Everything gets deallocated except the master jpeg_compress_struct itself
|
||||
and the error manager struct. Both of these are supplied by the application
|
||||
and must be freed, if necessary, by the application. (Often they are on
|
||||
the stack and so don't need to be freed anyway.)
|
||||
Closing a data source or destination, if necessary, is the application's
|
||||
responsibility. }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
procedure jpeg_destroy (cinfo : j_common_ptr);
|
||||
begin
|
||||
{ We need only tell the memory manager to release everything. }
|
||||
{ NB: mem pointer is NIL if memory mgr failed to initialize. }
|
||||
if (cinfo^.mem <> NIL) then
|
||||
cinfo^.mem^.self_destruct (cinfo);
|
||||
cinfo^.mem := NIL; { be safe if jpeg_destroy is called twice }
|
||||
cinfo^.global_state := 0; { mark it destroyed }
|
||||
end;
|
||||
|
||||
|
||||
{ Convenience routines for allocating quantization and Huffman tables.
|
||||
(Would jutils.c be a more reasonable place to put these?) }
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR;
|
||||
var
|
||||
tbl : JQUANT_TBL_PTR;
|
||||
begin
|
||||
tbl := JQUANT_TBL_PTR(
|
||||
cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL))
|
||||
);
|
||||
tbl^.sent_table := FALSE; { make sure this is false in any new table }
|
||||
jpeg_alloc_quant_table := tbl;
|
||||
end;
|
||||
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR;
|
||||
var
|
||||
tbl : JHUFF_TBL_PTR;
|
||||
begin
|
||||
tbl := JHUFF_TBL_PTR(
|
||||
cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL))
|
||||
);
|
||||
tbl^.sent_table := FALSE; { make sure this is false in any new table }
|
||||
jpeg_alloc_huff_table := tbl;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -1,124 +1,126 @@
|
||||
{ ----------------------- JPEG_INTERNAL_OPTIONS ---------------------- }
|
||||
|
||||
|
||||
{ These defines indicate whether to include various optional functions.
|
||||
Undefining some of these symbols will produce a smaller but less capable
|
||||
library. Note that you can leave certain source files out of the
|
||||
compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
(You may HAVE to do that if your compiler doesn't like null source files.)}
|
||||
|
||||
|
||||
{ Arithmetic coding is unsupported for legal reasons. Complaints to IBM. }
|
||||
|
||||
{ Capability options common to encoder and decoder: }
|
||||
|
||||
{$define DCT_ISLOW_SUPPORTED} { slow but accurate integer algorithm }
|
||||
{$define DCT_IFAST_SUPPORTED} { faster, less accurate integer method }
|
||||
{$define DCT_FLOAT_SUPPORTED} { floating-point: accurate, fast on fast HW }
|
||||
|
||||
{ Encoder capability options: }
|
||||
|
||||
{$undef C_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? }
|
||||
{$define C_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? }
|
||||
{$define C_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)}
|
||||
{$define ENTROPY_OPT_SUPPORTED} { Optimization of entropy coding parms? }
|
||||
{ Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
precision, so jchuff.c normally uses entropy optimization to compute
|
||||
usable tables for higher precision. If you don't want to do optimization,
|
||||
you'll have to supply different default Huffman tables.
|
||||
The exact same statements apply for progressive JPEG: the default tables
|
||||
don't work for progressive mode. (This may get fixed, however.) }
|
||||
|
||||
{$define INPUT_SMOOTHING_SUPPORTED} { Input image smoothing option? }
|
||||
|
||||
{ Decoder capability options: }
|
||||
|
||||
{$undef D_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? }
|
||||
{$define D_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? }
|
||||
{$define D_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)}
|
||||
{$define SAVE_MARKERS_SUPPORTED} { jpeg_save_markers() needed? }
|
||||
{$define BLOCK_SMOOTHING_SUPPORTED} { Block smoothing? (Progressive only) }
|
||||
{$define IDCT_SCALING_SUPPORTED} { Output rescaling via IDCT? }
|
||||
{$undef UPSAMPLE_SCALING_SUPPORTED} { Output rescaling at upsample stage? }
|
||||
{$define UPSAMPLE_MERGING_SUPPORTED} { Fast path for sloppy upsampling? }
|
||||
{$define QUANT_1PASS_SUPPORTED} { 1-pass color quantization? }
|
||||
{$define QUANT_2PASS_SUPPORTED} { 2-pass color quantization? }
|
||||
|
||||
{ If you happen not to want the image transform support, disable it here }
|
||||
{$define TRANSFORMS_SUPPORTED}
|
||||
|
||||
{ more capability options later, no doubt }
|
||||
|
||||
{$ifopt I+} {$define IOcheck} {$endif}
|
||||
|
||||
{ ------------------------------------------------------------------------ }
|
||||
|
||||
{$define USE_FMEM} { Borland has _fmemcpy() and _fmemset() }
|
||||
|
||||
{$define FMEMCOPY}
|
||||
{$define FMEMZERO}
|
||||
|
||||
{$define DCTSIZE_IS_8} { e.g. unroll the inner loop }
|
||||
{$define RIGHT_SHIFT_IS_UNSIGNED}
|
||||
{$undef AVOID_TABLES}
|
||||
{$undef FAST_DIVIDE}
|
||||
|
||||
{$define BITS_IN_JSAMPLE_IS_8}
|
||||
|
||||
{----------------------------------------------------------------}
|
||||
{ for test of 12 bit JPEG code only. !! }
|
||||
{-- $undef BITS_IN_JSAMPLE_IS_8}
|
||||
{----------------------------------------------------------------}
|
||||
|
||||
//{$define RGB_RED_IS_0}
|
||||
{ !CHANGE: This must be defined for Delphi/Kylix/FPC }
|
||||
{$define RGB_RED_IS_2} { RGB byte order }
|
||||
|
||||
|
||||
{$define RGB_PIXELSIZE_IS_3}
|
||||
{$define SLOW_SHIFT_32}
|
||||
{$undef NO_ZERO_ROW_TEST}
|
||||
|
||||
{$define USE_MSDOS_MEMMGR} { Define this if you use jmemdos.c }
|
||||
{$define XMS_SUPPORTED}
|
||||
{$define EMS_SUPPORTED}
|
||||
|
||||
{$undef MEM_STATS} { Write out memory usage }
|
||||
{$define AM_MEMORY_MANAGER} { we define jvirt_Xarray_control structs }
|
||||
|
||||
{$undef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
{$define PROGRESS_REPORT}
|
||||
{$define TWO_FILE_COMMANDLINE}
|
||||
{$undef BMP_SUPPORTED}
|
||||
{$undef PPM_SUPPORTED}
|
||||
{$undef GIF_SUPPORTED}
|
||||
{$undef RLE_SUPPORTED}
|
||||
{$undef TARGA_SUPPORTED}
|
||||
{$define EXT_SWITCH}
|
||||
|
||||
{$ifndef BITS_IN_JSAMPLE_IS_8} { for 12 bit samples }
|
||||
{$undef BMP_SUPPORTED}
|
||||
{$undef RLE_SUPPORTED}
|
||||
{$undef TARGA_SUPPORTED}
|
||||
{$endif}
|
||||
|
||||
|
||||
{!CHANGE: Allowed only for Delphi}
|
||||
{$undef BASM16} { for TP7 - use BASM for fast multiply }
|
||||
{$ifdef Win32}
|
||||
{$ifndef FPC}
|
||||
{$define BASM} { jidctint with BASM for Delphi 2/3 }
|
||||
{$undef RGB_RED_IS_0} { BGR byte order in JQUANT2 }
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$ifdef FPC}
|
||||
{$MODE DELPHI}
|
||||
{$endif}
|
||||
|
||||
{!CHANGE: Added this}
|
||||
{$define Delphi_Stream}
|
||||
{$Q-}
|
||||
|
||||
{ ----------------------- JPEG_INTERNAL_OPTIONS ---------------------- }
|
||||
|
||||
|
||||
{ These defines indicate whether to include various optional functions.
|
||||
Undefining some of these symbols will produce a smaller but less capable
|
||||
library. Note that you can leave certain source files out of the
|
||||
compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
(You may HAVE to do that if your compiler doesn't like null source files.)}
|
||||
|
||||
|
||||
{ Arithmetic coding is unsupported for legal reasons. Complaints to IBM. }
|
||||
|
||||
{ Capability options common to encoder and decoder: }
|
||||
|
||||
{$define DCT_ISLOW_SUPPORTED} { slow but accurate integer algorithm }
|
||||
{$define DCT_IFAST_SUPPORTED} { faster, less accurate integer method }
|
||||
{$define DCT_FLOAT_SUPPORTED} { floating-point: accurate, fast on fast HW }
|
||||
|
||||
{ Encoder capability options: }
|
||||
|
||||
{$undef C_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? }
|
||||
{$define C_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? }
|
||||
{$define C_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)}
|
||||
{$define ENTROPY_OPT_SUPPORTED} { Optimization of entropy coding parms? }
|
||||
{ Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
precision, so jchuff.c normally uses entropy optimization to compute
|
||||
usable tables for higher precision. If you don't want to do optimization,
|
||||
you'll have to supply different default Huffman tables.
|
||||
The exact same statements apply for progressive JPEG: the default tables
|
||||
don't work for progressive mode. (This may get fixed, however.) }
|
||||
|
||||
{$define INPUT_SMOOTHING_SUPPORTED} { Input image smoothing option? }
|
||||
|
||||
{ Decoder capability options: }
|
||||
|
||||
{$undef D_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? }
|
||||
{$define D_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? }
|
||||
{$define D_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)}
|
||||
{$define SAVE_MARKERS_SUPPORTED} { jpeg_save_markers() needed? }
|
||||
{$define BLOCK_SMOOTHING_SUPPORTED} { Block smoothing? (Progressive only) }
|
||||
{$define IDCT_SCALING_SUPPORTED} { Output rescaling via IDCT? }
|
||||
{$undef UPSAMPLE_SCALING_SUPPORTED} { Output rescaling at upsample stage? }
|
||||
{$define UPSAMPLE_MERGING_SUPPORTED} { Fast path for sloppy upsampling? }
|
||||
{$define QUANT_1PASS_SUPPORTED} { 1-pass color quantization? }
|
||||
{$define QUANT_2PASS_SUPPORTED} { 2-pass color quantization? }
|
||||
|
||||
{ If you happen not to want the image transform support, disable it here }
|
||||
{$define TRANSFORMS_SUPPORTED}
|
||||
|
||||
{ more capability options later, no doubt }
|
||||
|
||||
{$ifopt I+} {$define IOcheck} {$endif}
|
||||
|
||||
{ ------------------------------------------------------------------------ }
|
||||
|
||||
{$define USE_FMEM} { Borland has _fmemcpy() and _fmemset() }
|
||||
|
||||
{$define FMEMCOPY}
|
||||
{$define FMEMZERO}
|
||||
|
||||
{$define DCTSIZE_IS_8} { e.g. unroll the inner loop }
|
||||
{$define RIGHT_SHIFT_IS_UNSIGNED}
|
||||
{$undef AVOID_TABLES}
|
||||
{$undef FAST_DIVIDE}
|
||||
|
||||
{$define BITS_IN_JSAMPLE_IS_8}
|
||||
|
||||
{----------------------------------------------------------------}
|
||||
{ for test of 12 bit JPEG code only. !! }
|
||||
{-- $undef BITS_IN_JSAMPLE_IS_8}
|
||||
{----------------------------------------------------------------}
|
||||
|
||||
//{$define RGB_RED_IS_0}
|
||||
{ !CHANGE: This must be defined for Delphi/Kylix/FPC }
|
||||
{$define RGB_RED_IS_2} { RGB byte order }
|
||||
|
||||
|
||||
{$define RGB_PIXELSIZE_IS_3}
|
||||
{$define SLOW_SHIFT_32}
|
||||
{$undef NO_ZERO_ROW_TEST}
|
||||
|
||||
{$define USE_MSDOS_MEMMGR} { Define this if you use jmemdos.c }
|
||||
{$define XMS_SUPPORTED}
|
||||
{$define EMS_SUPPORTED}
|
||||
|
||||
{$undef MEM_STATS} { Write out memory usage }
|
||||
{$define AM_MEMORY_MANAGER} { we define jvirt_Xarray_control structs }
|
||||
|
||||
{$undef FULL_MAIN_BUFFER_SUPPORTED}
|
||||
|
||||
{$define PROGRESS_REPORT}
|
||||
{$define TWO_FILE_COMMANDLINE}
|
||||
{$undef BMP_SUPPORTED}
|
||||
{$undef PPM_SUPPORTED}
|
||||
{$undef GIF_SUPPORTED}
|
||||
{$undef RLE_SUPPORTED}
|
||||
{$undef TARGA_SUPPORTED}
|
||||
{$define EXT_SWITCH}
|
||||
|
||||
{$ifndef BITS_IN_JSAMPLE_IS_8} { for 12 bit samples }
|
||||
{$undef BMP_SUPPORTED}
|
||||
{$undef RLE_SUPPORTED}
|
||||
{$undef TARGA_SUPPORTED}
|
||||
{$endif}
|
||||
|
||||
|
||||
{!CHANGE: Allowed only for Delphi}
|
||||
{$undef BASM16} { for TP7 - use BASM for fast multiply }
|
||||
{$ifdef Win32}
|
||||
{$ifndef FPC}
|
||||
{$define BASM} { jidctint with BASM for Delphi 2/3 }
|
||||
{$undef RGB_RED_IS_0} { BGR byte order in JQUANT2 }
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$ifdef FPC}
|
||||
{$MODE DELPHI}
|
||||
{$endif}
|
||||
|
||||
{!CHANGE: Added this}
|
||||
{$define Delphi_Stream}
|
||||
{$Q-}
|
||||
{$MINENUMSIZE 4}
|
||||
{$ALIGN 8}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,406 +1,406 @@
|
||||
unit imjcprepct;
|
||||
|
||||
{ Original : jcprepct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file contains the compression preprocessing controller.
|
||||
This controller manages the color conversion, downsampling,
|
||||
and edge expansion steps.
|
||||
|
||||
Most of the complexity here is associated with buffering input rows
|
||||
as required by the downsampler. See the comments at the head of
|
||||
jcsample.c for the downsampler's needs. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjpeglib,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjinclude,
|
||||
imjutils;
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_prep_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{ At present, jcsample.c can request context rows only for smoothing.
|
||||
In the future, we might also need context rows for CCIR601 sampling
|
||||
or other more-complex downsampling procedures. The code to support
|
||||
context rows should be compiled only if needed. }
|
||||
|
||||
{$ifdef INPUT_SMOOTHING_SUPPORTED}
|
||||
{$define CONTEXT_ROWS_SUPPORTED}
|
||||
{$endif}
|
||||
|
||||
|
||||
{ For the simple (no-context-row) case, we just need to buffer one
|
||||
row group's worth of pixels for the downsampling step. At the bottom of
|
||||
the image, we pad to a full row group by replicating the last pixel row.
|
||||
The downsampler's last output row is then replicated if needed to pad
|
||||
out to a full iMCU row.
|
||||
|
||||
When providing context rows, we must buffer three row groups' worth of
|
||||
pixels. Three row groups are physically allocated, but the row pointer
|
||||
arrays are made five row groups high, with the extra pointers above and
|
||||
below "wrapping around" to point to the last and first real row groups.
|
||||
This allows the downsampler to access the proper context rows.
|
||||
At the top and bottom of the image, we create dummy context rows by
|
||||
copying the first or last real pixel row. This copying could be avoided
|
||||
by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
|
||||
trouble on the compression side. }
|
||||
|
||||
|
||||
{ Private buffer controller object }
|
||||
|
||||
type
|
||||
my_prep_ptr = ^my_prep_controller;
|
||||
my_prep_controller = record
|
||||
pub : jpeg_c_prep_controller; { public fields }
|
||||
|
||||
{ Downsampling input buffer. This buffer holds color-converted data
|
||||
until we have enough to do a downsample step. }
|
||||
|
||||
color_buf : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
|
||||
|
||||
rows_to_go : JDIMENSION; { counts rows remaining in source image }
|
||||
next_buf_row : int; { index of next row to store in color_buf }
|
||||
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED} { only needed for context case }
|
||||
this_row_group : int; { starting row index of group to process }
|
||||
next_buf_stop : int; { downsample when we reach this index }
|
||||
{$endif}
|
||||
end; {my_prep_controller;}
|
||||
|
||||
|
||||
{ Initialize for a processing pass. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass_prep (cinfo : j_compress_ptr;
|
||||
pass_mode : J_BUF_MODE );
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
|
||||
if (pass_mode <> JBUF_PASS_THRU) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
|
||||
{ Initialize total-height counter for detecting bottom of image }
|
||||
prep^.rows_to_go := cinfo^.image_height;
|
||||
{ Mark the conversion buffer empty }
|
||||
prep^.next_buf_row := 0;
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
{ Preset additional state variables for context mode.
|
||||
These aren't used in non-context mode, so we needn't test which mode. }
|
||||
prep^.this_row_group := 0;
|
||||
{ Set next_buf_stop to stop after two row groups have been read in. }
|
||||
prep^.next_buf_stop := 2 * cinfo^.max_v_samp_factor;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
|
||||
{ Expand an image vertically from height input_rows to height output_rows,
|
||||
by duplicating the bottom row. }
|
||||
|
||||
{LOCAL}
|
||||
procedure expand_bottom_edge (image_data : JSAMPARRAY;
|
||||
num_cols : JDIMENSION;
|
||||
input_rows : int;
|
||||
output_rows : int);
|
||||
var
|
||||
{register} row : int;
|
||||
begin
|
||||
for row := input_rows to pred(output_rows) do
|
||||
begin
|
||||
jcopy_sample_rows(image_data, input_rows-1, image_data, row,
|
||||
1, num_cols);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Process some data in the simple no-context case.
|
||||
|
||||
Preprocessor output data is counted in "row groups". A row group
|
||||
is defined to be v_samp_factor sample rows of each component.
|
||||
Downsampling will produce this much data from each max_v_samp_factor
|
||||
input rows. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure pre_process_data (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION;
|
||||
output_buf : JSAMPIMAGE;
|
||||
var out_row_group_ctr : JDIMENSION;
|
||||
out_row_groups_avail : JDIMENSION);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
numrows, ci : int;
|
||||
inrows : JDIMENSION;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
var
|
||||
local_input_buf : JSAMPARRAY;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
|
||||
while (in_row_ctr < in_rows_avail) and
|
||||
(out_row_group_ctr < out_row_groups_avail) do
|
||||
begin
|
||||
{ Do color conversion to fill the conversion buffer. }
|
||||
inrows := in_rows_avail - in_row_ctr;
|
||||
numrows := cinfo^.max_v_samp_factor - prep^.next_buf_row;
|
||||
{numrows := int( MIN(JDIMENSION(numrows), inrows) );}
|
||||
if inrows < JDIMENSION(numrows) then
|
||||
numrows := int(inrows);
|
||||
local_input_buf := JSAMPARRAY(@(input_buf^[in_row_ctr]));
|
||||
cinfo^.cconvert^.color_convert (cinfo, local_input_buf,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION(prep^.next_buf_row),
|
||||
numrows);
|
||||
Inc(in_row_ctr, numrows);
|
||||
Inc(prep^.next_buf_row, numrows);
|
||||
Dec(prep^.rows_to_go, numrows);
|
||||
{ If at bottom of image, pad to fill the conversion buffer. }
|
||||
if (prep^.rows_to_go = 0) and
|
||||
(prep^.next_buf_row < cinfo^.max_v_samp_factor) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width,
|
||||
prep^.next_buf_row, cinfo^.max_v_samp_factor);
|
||||
end;
|
||||
prep^.next_buf_row := cinfo^.max_v_samp_factor;
|
||||
end;
|
||||
{ If we've filled the conversion buffer, empty it. }
|
||||
if (prep^.next_buf_row = cinfo^.max_v_samp_factor) then
|
||||
begin
|
||||
cinfo^.downsample^.downsample (cinfo,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION (0),
|
||||
output_buf,
|
||||
out_row_group_ctr);
|
||||
prep^.next_buf_row := 0;
|
||||
Inc(out_row_group_ctr);;
|
||||
end;
|
||||
{ If at bottom of image, pad the output to a full iMCU height.
|
||||
Note we assume the caller is providing a one-iMCU-height output buffer! }
|
||||
if (prep^.rows_to_go = 0) and
|
||||
(out_row_group_ctr < out_row_groups_avail) then
|
||||
begin
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(output_buf^[ci],
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
int (out_row_group_ctr) * compptr^.v_samp_factor,
|
||||
int (out_row_groups_avail) * compptr^.v_samp_factor);
|
||||
Inc(compptr);
|
||||
end;
|
||||
out_row_group_ctr := out_row_groups_avail;
|
||||
break; { can exit outer loop without test }
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
|
||||
{ Process some data in the context case. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure pre_process_context (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION;
|
||||
output_buf : JSAMPIMAGE;
|
||||
var out_row_group_ctr : JDIMENSION;
|
||||
out_row_groups_avail : JDIMENSION);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
numrows, ci : int;
|
||||
buf_height : int;
|
||||
inrows : JDIMENSION;
|
||||
var
|
||||
row : int;
|
||||
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
buf_height := cinfo^.max_v_samp_factor * 3;
|
||||
|
||||
while (out_row_group_ctr < out_row_groups_avail) do
|
||||
begin
|
||||
if (in_row_ctr < in_rows_avail) then
|
||||
begin
|
||||
{ Do color conversion to fill the conversion buffer. }
|
||||
inrows := in_rows_avail - in_row_ctr;
|
||||
numrows := prep^.next_buf_stop - prep^.next_buf_row;
|
||||
{numrows := int ( MIN( JDIMENSION(numrows), inrows) );}
|
||||
if inrows < JDIMENSION(numrows) then
|
||||
numrows := int(inrows);
|
||||
cinfo^.cconvert^.color_convert (cinfo,
|
||||
JSAMPARRAY(@input_buf^[in_row_ctr]),
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION (prep^.next_buf_row),
|
||||
numrows);
|
||||
{ Pad at top of image, if first time through }
|
||||
if (prep^.rows_to_go = cinfo^.image_height) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
for row := 1 to cinfo^.max_v_samp_factor do
|
||||
begin
|
||||
jcopy_sample_rows(prep^.color_buf[ci], 0,
|
||||
prep^.color_buf[ci], -row,
|
||||
1, cinfo^.image_width);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Inc(in_row_ctr, numrows);
|
||||
Inc(prep^.next_buf_row, numrows);
|
||||
Dec(prep^.rows_to_go, numrows);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ Return for more data, unless we are at the bottom of the image. }
|
||||
if (prep^.rows_to_go <> 0) then
|
||||
break;
|
||||
{ When at bottom of image, pad to fill the conversion buffer. }
|
||||
if (prep^.next_buf_row < prep^.next_buf_stop) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width,
|
||||
prep^.next_buf_row, prep^.next_buf_stop);
|
||||
end;
|
||||
prep^.next_buf_row := prep^.next_buf_stop;
|
||||
end;
|
||||
end;
|
||||
{ If we've gotten enough data, downsample a row group. }
|
||||
if (prep^.next_buf_row = prep^.next_buf_stop) then
|
||||
begin
|
||||
cinfo^.downsample^.downsample (cinfo,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION(prep^.this_row_group),
|
||||
output_buf,
|
||||
out_row_group_ctr);
|
||||
Inc(out_row_group_ctr);
|
||||
{ Advance pointers with wraparound as necessary. }
|
||||
Inc(prep^.this_row_group, cinfo^.max_v_samp_factor);
|
||||
if (prep^.this_row_group >= buf_height) then
|
||||
prep^.this_row_group := 0;
|
||||
if (prep^.next_buf_row >= buf_height) then
|
||||
prep^.next_buf_row := 0;
|
||||
prep^.next_buf_stop := prep^.next_buf_row + cinfo^.max_v_samp_factor;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Create the wrapped-around downsampling input buffer needed for context mode. }
|
||||
|
||||
{LOCAL}
|
||||
procedure create_context_buffer (cinfo : j_compress_ptr);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
rgroup_height : int;
|
||||
ci, i : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
true_buffer, fake_buffer : JSAMPARRAY;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
rgroup_height := cinfo^.max_v_samp_factor;
|
||||
{ Grab enough space for fake row pointers for all the components;
|
||||
we need five row groups' worth of pointers for each component. }
|
||||
|
||||
fake_buffer := JSAMPARRAY(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
(cinfo^.num_components * 5 * rgroup_height) *
|
||||
SIZEOF(JSAMPROW)) );
|
||||
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
{ Allocate the actual buffer space (3 row groups) for this component.
|
||||
We make the buffer wide enough to allow the downsampler to edge-expand
|
||||
horizontally within the buffer, if it so chooses. }
|
||||
true_buffer := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE *
|
||||
cinfo^.max_h_samp_factor) div compptr^.h_samp_factor),
|
||||
JDIMENSION (3 * rgroup_height));
|
||||
{ Copy true buffer row pointers into the middle of the fake row array }
|
||||
MEMCOPY(JSAMPARRAY(@ fake_buffer^[rgroup_height]), true_buffer,
|
||||
3 * rgroup_height * SIZEOF(JSAMPROW));
|
||||
{ Fill in the above and below wraparound pointers }
|
||||
for i := 0 to pred(rgroup_height) do
|
||||
begin
|
||||
fake_buffer^[i] := true_buffer^[2 * rgroup_height + i];
|
||||
fake_buffer^[4 * rgroup_height + i] := true_buffer^[i];
|
||||
end;
|
||||
prep^.color_buf[ci] := JSAMPARRAY(@ fake_buffer^[rgroup_height]);
|
||||
Inc(JSAMPROW_PTR(fake_buffer), 5 * rgroup_height); { point to space for next component }
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$endif} { CONTEXT_ROWS_SUPPORTED }
|
||||
|
||||
|
||||
{ Initialize preprocessing controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_prep_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
begin
|
||||
|
||||
if (need_full_buffer) then { safety check }
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
|
||||
prep := my_prep_ptr(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(my_prep_controller)) );
|
||||
cinfo^.prep := jpeg_c_prep_controller_ptr(prep);
|
||||
prep^.pub.start_pass := start_pass_prep;
|
||||
|
||||
{ Allocate the color conversion buffer.
|
||||
We make the buffer wide enough to allow the downsampler to edge-expand
|
||||
horizontally within the buffer, if it so chooses. }
|
||||
|
||||
if (cinfo^.downsample^.need_context_rows) then
|
||||
begin
|
||||
{ Set up to provide context rows }
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
prep^.pub.pre_process_data := pre_process_context;
|
||||
create_context_buffer(cinfo);
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ No context, just make it tall enough for one row group }
|
||||
prep^.pub.pre_process_data := pre_process_data;
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
prep^.color_buf[ci] := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE *
|
||||
cinfo^.max_h_samp_factor) div compptr^.h_samp_factor),
|
||||
JDIMENSION(cinfo^.max_v_samp_factor) );
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjcprepct;
|
||||
|
||||
{ Original : jcprepct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file contains the compression preprocessing controller.
|
||||
This controller manages the color conversion, downsampling,
|
||||
and edge expansion steps.
|
||||
|
||||
Most of the complexity here is associated with buffering input rows
|
||||
as required by the downsampler. See the comments at the head of
|
||||
jcsample.c for the downsampler's needs. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjpeglib,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjinclude,
|
||||
imjutils;
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_prep_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{ At present, jcsample.c can request context rows only for smoothing.
|
||||
In the future, we might also need context rows for CCIR601 sampling
|
||||
or other more-complex downsampling procedures. The code to support
|
||||
context rows should be compiled only if needed. }
|
||||
|
||||
{$ifdef INPUT_SMOOTHING_SUPPORTED}
|
||||
{$define CONTEXT_ROWS_SUPPORTED}
|
||||
{$endif}
|
||||
|
||||
|
||||
{ For the simple (no-context-row) case, we just need to buffer one
|
||||
row group's worth of pixels for the downsampling step. At the bottom of
|
||||
the image, we pad to a full row group by replicating the last pixel row.
|
||||
The downsampler's last output row is then replicated if needed to pad
|
||||
out to a full iMCU row.
|
||||
|
||||
When providing context rows, we must buffer three row groups' worth of
|
||||
pixels. Three row groups are physically allocated, but the row pointer
|
||||
arrays are made five row groups high, with the extra pointers above and
|
||||
below "wrapping around" to point to the last and first real row groups.
|
||||
This allows the downsampler to access the proper context rows.
|
||||
At the top and bottom of the image, we create dummy context rows by
|
||||
copying the first or last real pixel row. This copying could be avoided
|
||||
by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
|
||||
trouble on the compression side. }
|
||||
|
||||
|
||||
{ Private buffer controller object }
|
||||
|
||||
type
|
||||
my_prep_ptr = ^my_prep_controller;
|
||||
my_prep_controller = record
|
||||
pub : jpeg_c_prep_controller; { public fields }
|
||||
|
||||
{ Downsampling input buffer. This buffer holds color-converted data
|
||||
until we have enough to do a downsample step. }
|
||||
|
||||
color_buf : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
|
||||
|
||||
rows_to_go : JDIMENSION; { counts rows remaining in source image }
|
||||
next_buf_row : int; { index of next row to store in color_buf }
|
||||
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED} { only needed for context case }
|
||||
this_row_group : int; { starting row index of group to process }
|
||||
next_buf_stop : int; { downsample when we reach this index }
|
||||
{$endif}
|
||||
end; {my_prep_controller;}
|
||||
|
||||
|
||||
{ Initialize for a processing pass. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass_prep (cinfo : j_compress_ptr;
|
||||
pass_mode : J_BUF_MODE );
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
|
||||
if (pass_mode <> JBUF_PASS_THRU) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
|
||||
{ Initialize total-height counter for detecting bottom of image }
|
||||
prep^.rows_to_go := cinfo^.image_height;
|
||||
{ Mark the conversion buffer empty }
|
||||
prep^.next_buf_row := 0;
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
{ Preset additional state variables for context mode.
|
||||
These aren't used in non-context mode, so we needn't test which mode. }
|
||||
prep^.this_row_group := 0;
|
||||
{ Set next_buf_stop to stop after two row groups have been read in. }
|
||||
prep^.next_buf_stop := 2 * cinfo^.max_v_samp_factor;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
|
||||
{ Expand an image vertically from height input_rows to height output_rows,
|
||||
by duplicating the bottom row. }
|
||||
|
||||
{LOCAL}
|
||||
procedure expand_bottom_edge (image_data : JSAMPARRAY;
|
||||
num_cols : JDIMENSION;
|
||||
input_rows : int;
|
||||
output_rows : int);
|
||||
var
|
||||
{register} row : int;
|
||||
begin
|
||||
for row := input_rows to pred(output_rows) do
|
||||
begin
|
||||
jcopy_sample_rows(image_data, input_rows-1, image_data, row,
|
||||
1, num_cols);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Process some data in the simple no-context case.
|
||||
|
||||
Preprocessor output data is counted in "row groups". A row group
|
||||
is defined to be v_samp_factor sample rows of each component.
|
||||
Downsampling will produce this much data from each max_v_samp_factor
|
||||
input rows. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure pre_process_data (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION;
|
||||
output_buf : JSAMPIMAGE;
|
||||
var out_row_group_ctr : JDIMENSION;
|
||||
out_row_groups_avail : JDIMENSION);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
numrows, ci : int;
|
||||
inrows : JDIMENSION;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
var
|
||||
local_input_buf : JSAMPARRAY;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
|
||||
while (in_row_ctr < in_rows_avail) and
|
||||
(out_row_group_ctr < out_row_groups_avail) do
|
||||
begin
|
||||
{ Do color conversion to fill the conversion buffer. }
|
||||
inrows := in_rows_avail - in_row_ctr;
|
||||
numrows := cinfo^.max_v_samp_factor - prep^.next_buf_row;
|
||||
{numrows := int( MIN(JDIMENSION(numrows), inrows) );}
|
||||
if inrows < JDIMENSION(numrows) then
|
||||
numrows := int(inrows);
|
||||
local_input_buf := JSAMPARRAY(@(input_buf^[in_row_ctr]));
|
||||
cinfo^.cconvert^.color_convert (cinfo, local_input_buf,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION(prep^.next_buf_row),
|
||||
numrows);
|
||||
Inc(in_row_ctr, numrows);
|
||||
Inc(prep^.next_buf_row, numrows);
|
||||
Dec(prep^.rows_to_go, numrows);
|
||||
{ If at bottom of image, pad to fill the conversion buffer. }
|
||||
if (prep^.rows_to_go = 0) and
|
||||
(prep^.next_buf_row < cinfo^.max_v_samp_factor) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width,
|
||||
prep^.next_buf_row, cinfo^.max_v_samp_factor);
|
||||
end;
|
||||
prep^.next_buf_row := cinfo^.max_v_samp_factor;
|
||||
end;
|
||||
{ If we've filled the conversion buffer, empty it. }
|
||||
if (prep^.next_buf_row = cinfo^.max_v_samp_factor) then
|
||||
begin
|
||||
cinfo^.downsample^.downsample (cinfo,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION (0),
|
||||
output_buf,
|
||||
out_row_group_ctr);
|
||||
prep^.next_buf_row := 0;
|
||||
Inc(out_row_group_ctr);;
|
||||
end;
|
||||
{ If at bottom of image, pad the output to a full iMCU height.
|
||||
Note we assume the caller is providing a one-iMCU-height output buffer! }
|
||||
if (prep^.rows_to_go = 0) and
|
||||
(out_row_group_ctr < out_row_groups_avail) then
|
||||
begin
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(output_buf^[ci],
|
||||
compptr^.width_in_blocks * DCTSIZE,
|
||||
int (out_row_group_ctr) * compptr^.v_samp_factor,
|
||||
int (out_row_groups_avail) * compptr^.v_samp_factor);
|
||||
Inc(compptr);
|
||||
end;
|
||||
out_row_group_ctr := out_row_groups_avail;
|
||||
break; { can exit outer loop without test }
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
|
||||
{ Process some data in the context case. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure pre_process_context (cinfo : j_compress_ptr;
|
||||
input_buf : JSAMPARRAY;
|
||||
var in_row_ctr : JDIMENSION;
|
||||
in_rows_avail : JDIMENSION;
|
||||
output_buf : JSAMPIMAGE;
|
||||
var out_row_group_ctr : JDIMENSION;
|
||||
out_row_groups_avail : JDIMENSION);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
numrows, ci : int;
|
||||
buf_height : int;
|
||||
inrows : JDIMENSION;
|
||||
var
|
||||
row : int;
|
||||
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
buf_height := cinfo^.max_v_samp_factor * 3;
|
||||
|
||||
while (out_row_group_ctr < out_row_groups_avail) do
|
||||
begin
|
||||
if (in_row_ctr < in_rows_avail) then
|
||||
begin
|
||||
{ Do color conversion to fill the conversion buffer. }
|
||||
inrows := in_rows_avail - in_row_ctr;
|
||||
numrows := prep^.next_buf_stop - prep^.next_buf_row;
|
||||
{numrows := int ( MIN( JDIMENSION(numrows), inrows) );}
|
||||
if inrows < JDIMENSION(numrows) then
|
||||
numrows := int(inrows);
|
||||
cinfo^.cconvert^.color_convert (cinfo,
|
||||
JSAMPARRAY(@input_buf^[in_row_ctr]),
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION (prep^.next_buf_row),
|
||||
numrows);
|
||||
{ Pad at top of image, if first time through }
|
||||
if (prep^.rows_to_go = cinfo^.image_height) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
for row := 1 to cinfo^.max_v_samp_factor do
|
||||
begin
|
||||
jcopy_sample_rows(prep^.color_buf[ci], 0,
|
||||
prep^.color_buf[ci], -row,
|
||||
1, cinfo^.image_width);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Inc(in_row_ctr, numrows);
|
||||
Inc(prep^.next_buf_row, numrows);
|
||||
Dec(prep^.rows_to_go, numrows);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ Return for more data, unless we are at the bottom of the image. }
|
||||
if (prep^.rows_to_go <> 0) then
|
||||
break;
|
||||
{ When at bottom of image, pad to fill the conversion buffer. }
|
||||
if (prep^.next_buf_row < prep^.next_buf_stop) then
|
||||
begin
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width,
|
||||
prep^.next_buf_row, prep^.next_buf_stop);
|
||||
end;
|
||||
prep^.next_buf_row := prep^.next_buf_stop;
|
||||
end;
|
||||
end;
|
||||
{ If we've gotten enough data, downsample a row group. }
|
||||
if (prep^.next_buf_row = prep^.next_buf_stop) then
|
||||
begin
|
||||
cinfo^.downsample^.downsample (cinfo,
|
||||
JSAMPIMAGE(@prep^.color_buf),
|
||||
JDIMENSION(prep^.this_row_group),
|
||||
output_buf,
|
||||
out_row_group_ctr);
|
||||
Inc(out_row_group_ctr);
|
||||
{ Advance pointers with wraparound as necessary. }
|
||||
Inc(prep^.this_row_group, cinfo^.max_v_samp_factor);
|
||||
if (prep^.this_row_group >= buf_height) then
|
||||
prep^.this_row_group := 0;
|
||||
if (prep^.next_buf_row >= buf_height) then
|
||||
prep^.next_buf_row := 0;
|
||||
prep^.next_buf_stop := prep^.next_buf_row + cinfo^.max_v_samp_factor;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Create the wrapped-around downsampling input buffer needed for context mode. }
|
||||
|
||||
{LOCAL}
|
||||
procedure create_context_buffer (cinfo : j_compress_ptr);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
rgroup_height : int;
|
||||
ci, i : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
true_buffer, fake_buffer : JSAMPARRAY;
|
||||
begin
|
||||
prep := my_prep_ptr (cinfo^.prep);
|
||||
rgroup_height := cinfo^.max_v_samp_factor;
|
||||
{ Grab enough space for fake row pointers for all the components;
|
||||
we need five row groups' worth of pointers for each component. }
|
||||
|
||||
fake_buffer := JSAMPARRAY(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
(cinfo^.num_components * 5 * rgroup_height) *
|
||||
SIZEOF(JSAMPROW)) );
|
||||
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
{ Allocate the actual buffer space (3 row groups) for this component.
|
||||
We make the buffer wide enough to allow the downsampler to edge-expand
|
||||
horizontally within the buffer, if it so chooses. }
|
||||
true_buffer := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE *
|
||||
cinfo^.max_h_samp_factor) div compptr^.h_samp_factor),
|
||||
JDIMENSION (3 * rgroup_height));
|
||||
{ Copy true buffer row pointers into the middle of the fake row array }
|
||||
MEMCOPY(JSAMPARRAY(@ fake_buffer^[rgroup_height]), true_buffer,
|
||||
3 * rgroup_height * SIZEOF(JSAMPROW));
|
||||
{ Fill in the above and below wraparound pointers }
|
||||
for i := 0 to pred(rgroup_height) do
|
||||
begin
|
||||
fake_buffer^[i] := true_buffer^[2 * rgroup_height + i];
|
||||
fake_buffer^[4 * rgroup_height + i] := true_buffer^[i];
|
||||
end;
|
||||
prep^.color_buf[ci] := JSAMPARRAY(@ fake_buffer^[rgroup_height]);
|
||||
Inc(JSAMPROW_PTR(fake_buffer), 5 * rgroup_height); { point to space for next component }
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$endif} { CONTEXT_ROWS_SUPPORTED }
|
||||
|
||||
|
||||
{ Initialize preprocessing controller. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_c_prep_controller (cinfo : j_compress_ptr;
|
||||
need_full_buffer : boolean);
|
||||
var
|
||||
prep : my_prep_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
begin
|
||||
|
||||
if (need_full_buffer) then { safety check }
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
|
||||
|
||||
prep := my_prep_ptr(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(my_prep_controller)) );
|
||||
cinfo^.prep := jpeg_c_prep_controller_ptr(prep);
|
||||
prep^.pub.start_pass := start_pass_prep;
|
||||
|
||||
{ Allocate the color conversion buffer.
|
||||
We make the buffer wide enough to allow the downsampler to edge-expand
|
||||
horizontally within the buffer, if it so chooses. }
|
||||
|
||||
if (cinfo^.downsample^.need_context_rows) then
|
||||
begin
|
||||
{ Set up to provide context rows }
|
||||
{$ifdef CONTEXT_ROWS_SUPPORTED}
|
||||
prep^.pub.pre_process_data := pre_process_context;
|
||||
create_context_buffer(cinfo);
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ No context, just make it tall enough for one row group }
|
||||
prep^.pub.pre_process_data := pre_process_data;
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
prep^.color_buf[ci] := cinfo^.mem^.alloc_sarray
|
||||
(j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE *
|
||||
cinfo^.max_h_samp_factor) div compptr^.h_samp_factor),
|
||||
JDIMENSION(cinfo^.max_v_samp_factor) );
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,377 +1,377 @@
|
||||
unit imjdapistd;
|
||||
|
||||
{ Original : jdapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
This file contains application interface code for the decompression half
|
||||
of the JPEG library. These are the "standard" API routines that are
|
||||
used in the normal full-decompression case. They are not used by a
|
||||
transcoding-only application. Note that if an application links in
|
||||
jpeg_start_decompress, it will end up linking in the entire decompressor.
|
||||
We thus must separate this file from jdapimin.c to avoid linking the
|
||||
whole decompression library into a transcoder. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjdmaster;
|
||||
|
||||
{ Read some scanlines of data from the JPEG decompressor.
|
||||
|
||||
The return value will be the number of lines actually read.
|
||||
This may be less than the number requested in several cases,
|
||||
including bottom of image, data source suspension, and operating
|
||||
modes that emit multiple scanlines at a time.
|
||||
|
||||
Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
an oversize buffer (max_lines > scanlines remaining) is not an error. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_scanlines (cinfo : j_decompress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
|
||||
{ Alternate entry point to read raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_raw_data (cinfo : j_decompress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
|
||||
{ Initialize for an output pass in buffered-image mode. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_output (cinfo : j_decompress_ptr;
|
||||
scan_number : int) : boolean;
|
||||
|
||||
{ Finish up after an output pass in buffered-image mode.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean;
|
||||
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
|
||||
{ Decompression initialization.
|
||||
jpeg_read_header must be completed before calling this.
|
||||
|
||||
If a multipass operating mode was selected, this will do all but the
|
||||
last pass, and thus may take a great deal of time.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ Forward declarations }
|
||||
{LOCAL}
|
||||
function output_pass_setup (cinfo : j_decompress_ptr) : boolean; forward;
|
||||
|
||||
{ Decompression initialization.
|
||||
jpeg_read_header must be completed before calling this.
|
||||
|
||||
If a multipass operating mode was selected, this will do all but the
|
||||
last pass, and thus may take a great deal of time.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean;
|
||||
var
|
||||
retcode : int;
|
||||
begin
|
||||
if (cinfo^.global_state = DSTATE_READY) then
|
||||
begin
|
||||
{ First call: initialize master control, select active modules }
|
||||
jinit_master_decompress(cinfo);
|
||||
if (cinfo^.buffered_image) then
|
||||
begin
|
||||
{ No more work here; expecting jpeg_start_output next }
|
||||
cinfo^.global_state := DSTATE_BUFIMAGE;
|
||||
jpeg_start_decompress := TRUE;
|
||||
exit;
|
||||
end;
|
||||
cinfo^.global_state := DSTATE_PRELOAD;
|
||||
end;
|
||||
if (cinfo^.global_state = DSTATE_PRELOAD) then
|
||||
begin
|
||||
{ If file has multiple scans, absorb them all into the coef buffer }
|
||||
if (cinfo^.inputctl^.has_multiple_scans) then
|
||||
begin
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
while TRUE do
|
||||
begin
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
{ Absorb some more input }
|
||||
retcode := cinfo^.inputctl^.consume_input (cinfo);
|
||||
if (retcode = JPEG_SUSPENDED) then
|
||||
begin
|
||||
jpeg_start_decompress := FALSE;
|
||||
exit;
|
||||
end;
|
||||
if (retcode = JPEG_REACHED_EOI) then
|
||||
break;
|
||||
{ Advance progress counter if appropriate }
|
||||
if (cinfo^.progress <> NIL) and
|
||||
((retcode = JPEG_ROW_COMPLETED) or (retcode = JPEG_REACHED_SOS)) then
|
||||
begin
|
||||
Inc(cinfo^.progress^.pass_counter);
|
||||
if (cinfo^.progress^.pass_counter >= cinfo^.progress^.pass_limit) then
|
||||
begin
|
||||
{ jdmaster underestimated number of scans; ratchet up one scan }
|
||||
Inc(cinfo^.progress^.pass_limit, long(cinfo^.total_iMCU_rows));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
end;
|
||||
cinfo^.output_scan_number := cinfo^.input_scan_number;
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Perform any dummy output passes, and set up for the final pass }
|
||||
jpeg_start_decompress := output_pass_setup(cinfo);
|
||||
end;
|
||||
|
||||
|
||||
{ Set up for an output pass, and perform any dummy pass(es) needed.
|
||||
Common subroutine for jpeg_start_decompress and jpeg_start_output.
|
||||
Entry: global_state := DSTATE_PRESCAN only if previously suspended.
|
||||
Exit: If done, returns TRUE and sets global_state for proper output mode.
|
||||
If suspended, returns FALSE and sets global_state := DSTATE_PRESCAN. }
|
||||
|
||||
{LOCAL}
|
||||
function output_pass_setup (cinfo : j_decompress_ptr) : boolean;
|
||||
var
|
||||
last_scanline : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
begin
|
||||
{ First call: do pass setup }
|
||||
cinfo^.master^.prepare_for_output_pass (cinfo);
|
||||
cinfo^.output_scanline := 0;
|
||||
cinfo^.global_state := DSTATE_PRESCAN;
|
||||
end;
|
||||
{ Loop over any required dummy passes }
|
||||
while (cinfo^.master^.is_dummy_pass) do
|
||||
begin
|
||||
{$ifdef QUANT_2PASS_SUPPORTED}
|
||||
{ Crank through the dummy pass }
|
||||
while (cinfo^.output_scanline < cinfo^.output_height) do
|
||||
begin
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
{ Process some data }
|
||||
last_scanline := cinfo^.output_scanline;
|
||||
cinfo^.main^.process_data (cinfo, JSAMPARRAY(NIL),
|
||||
cinfo^.output_scanline, {var}
|
||||
JDIMENSION(0));
|
||||
if (cinfo^.output_scanline = last_scanline) then
|
||||
begin
|
||||
output_pass_setup := FALSE; { No progress made, must suspend }
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
{ Finish up dummy pass, and set up for another one }
|
||||
cinfo^.master^.finish_output_pass (cinfo);
|
||||
cinfo^.master^.prepare_for_output_pass (cinfo);
|
||||
cinfo^.output_scanline := 0;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif} { QUANT_2PASS_SUPPORTED }
|
||||
end;
|
||||
{ Ready for application to drive output pass through
|
||||
jpeg_read_scanlines or jpeg_read_raw_data. }
|
||||
if cinfo^.raw_data_out then
|
||||
cinfo^.global_state := DSTATE_RAW_OK
|
||||
else
|
||||
cinfo^.global_state := DSTATE_SCANNING;
|
||||
output_pass_setup := TRUE;
|
||||
end;
|
||||
|
||||
|
||||
{ Read some scanlines of data from the JPEG decompressor.
|
||||
|
||||
The return value will be the number of lines actually read.
|
||||
This may be less than the number requested in several cases,
|
||||
including bottom of image, data source suspension, and operating
|
||||
modes that emit multiple scanlines at a time.
|
||||
|
||||
Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
an oversize buffer (max_lines > scanlines remaining) is not an error. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_scanlines (cinfo : j_decompress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
row_ctr : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_SCANNING) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.output_scanline >= cinfo^.output_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_read_scanlines := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Process some data }
|
||||
row_ctr := 0;
|
||||
cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, max_lines);
|
||||
Inc(cinfo^.output_scanline, row_ctr);
|
||||
jpeg_read_scanlines := row_ctr;
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate entry point to read raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_raw_data (cinfo : j_decompress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
lines_per_iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_RAW_OK) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.output_scanline >= cinfo^.output_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_read_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Verify that at least one iMCU row can be returned. }
|
||||
lines_per_iMCU_row := cinfo^.max_v_samp_factor * cinfo^.min_DCT_scaled_size;
|
||||
if (max_lines < lines_per_iMCU_row) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE);
|
||||
|
||||
{ Decompress directly into user's buffer. }
|
||||
if (cinfo^.coef^.decompress_data (cinfo, data) = 0) then
|
||||
begin
|
||||
jpeg_read_raw_data := 0; { suspension forced, can do nothing more }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ OK, we processed one iMCU row. }
|
||||
Inc(cinfo^.output_scanline, lines_per_iMCU_row);
|
||||
jpeg_read_raw_data := lines_per_iMCU_row;
|
||||
end;
|
||||
|
||||
|
||||
{ Additional entry points for buffered-image mode. }
|
||||
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
|
||||
{ Initialize for an output pass in buffered-image mode. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_output (cinfo : j_decompress_ptr;
|
||||
scan_number : int) : boolean;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_BUFIMAGE) and
|
||||
(cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Limit scan number to valid range }
|
||||
if (scan_number <= 0) then
|
||||
scan_number := 1;
|
||||
if (cinfo^.inputctl^.eoi_reached) and
|
||||
(scan_number > cinfo^.input_scan_number) then
|
||||
scan_number := cinfo^.input_scan_number;
|
||||
cinfo^.output_scan_number := scan_number;
|
||||
{ Perform any dummy output passes, and set up for the real pass }
|
||||
jpeg_start_output := output_pass_setup(cinfo);
|
||||
end;
|
||||
|
||||
|
||||
{ Finish up after an output pass in buffered-image mode.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean;
|
||||
begin
|
||||
if ((cinfo^.global_state = DSTATE_SCANNING) or
|
||||
(cinfo^.global_state = DSTATE_RAW_OK) and cinfo^.buffered_image) then
|
||||
begin
|
||||
{ Terminate this pass. }
|
||||
{ We do not require the whole pass to have been completed. }
|
||||
cinfo^.master^.finish_output_pass (cinfo);
|
||||
cinfo^.global_state := DSTATE_BUFPOST;
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> DSTATE_BUFPOST) then
|
||||
begin
|
||||
{ BUFPOST := repeat call after a suspension, anything else is error }
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
end;
|
||||
{ Read markers looking for SOS or EOI }
|
||||
while (cinfo^.input_scan_number <= cinfo^.output_scan_number) and
|
||||
(not cinfo^.inputctl^.eoi_reached) do
|
||||
begin
|
||||
if (cinfo^.inputctl^.consume_input (cinfo) = JPEG_SUSPENDED) then
|
||||
begin
|
||||
jpeg_finish_output := FALSE; { Suspend, come back later }
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
cinfo^.global_state := DSTATE_BUFIMAGE;
|
||||
jpeg_finish_output := TRUE;
|
||||
end;
|
||||
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
|
||||
end.
|
||||
|
||||
unit imjdapistd;
|
||||
|
||||
{ Original : jdapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
This file contains application interface code for the decompression half
|
||||
of the JPEG library. These are the "standard" API routines that are
|
||||
used in the normal full-decompression case. They are not used by a
|
||||
transcoding-only application. Note that if an application links in
|
||||
jpeg_start_decompress, it will end up linking in the entire decompressor.
|
||||
We thus must separate this file from jdapimin.c to avoid linking the
|
||||
whole decompression library into a transcoder. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjdmaster;
|
||||
|
||||
{ Read some scanlines of data from the JPEG decompressor.
|
||||
|
||||
The return value will be the number of lines actually read.
|
||||
This may be less than the number requested in several cases,
|
||||
including bottom of image, data source suspension, and operating
|
||||
modes that emit multiple scanlines at a time.
|
||||
|
||||
Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
an oversize buffer (max_lines > scanlines remaining) is not an error. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_scanlines (cinfo : j_decompress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
|
||||
{ Alternate entry point to read raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_raw_data (cinfo : j_decompress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
|
||||
{ Initialize for an output pass in buffered-image mode. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_output (cinfo : j_decompress_ptr;
|
||||
scan_number : int) : boolean;
|
||||
|
||||
{ Finish up after an output pass in buffered-image mode.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean;
|
||||
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
|
||||
{ Decompression initialization.
|
||||
jpeg_read_header must be completed before calling this.
|
||||
|
||||
If a multipass operating mode was selected, this will do all but the
|
||||
last pass, and thus may take a great deal of time.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ Forward declarations }
|
||||
{LOCAL}
|
||||
function output_pass_setup (cinfo : j_decompress_ptr) : boolean; forward;
|
||||
|
||||
{ Decompression initialization.
|
||||
jpeg_read_header must be completed before calling this.
|
||||
|
||||
If a multipass operating mode was selected, this will do all but the
|
||||
last pass, and thus may take a great deal of time.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean;
|
||||
var
|
||||
retcode : int;
|
||||
begin
|
||||
if (cinfo^.global_state = DSTATE_READY) then
|
||||
begin
|
||||
{ First call: initialize master control, select active modules }
|
||||
jinit_master_decompress(cinfo);
|
||||
if (cinfo^.buffered_image) then
|
||||
begin
|
||||
{ No more work here; expecting jpeg_start_output next }
|
||||
cinfo^.global_state := DSTATE_BUFIMAGE;
|
||||
jpeg_start_decompress := TRUE;
|
||||
exit;
|
||||
end;
|
||||
cinfo^.global_state := DSTATE_PRELOAD;
|
||||
end;
|
||||
if (cinfo^.global_state = DSTATE_PRELOAD) then
|
||||
begin
|
||||
{ If file has multiple scans, absorb them all into the coef buffer }
|
||||
if (cinfo^.inputctl^.has_multiple_scans) then
|
||||
begin
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
while TRUE do
|
||||
begin
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
{ Absorb some more input }
|
||||
retcode := cinfo^.inputctl^.consume_input (cinfo);
|
||||
if (retcode = JPEG_SUSPENDED) then
|
||||
begin
|
||||
jpeg_start_decompress := FALSE;
|
||||
exit;
|
||||
end;
|
||||
if (retcode = JPEG_REACHED_EOI) then
|
||||
break;
|
||||
{ Advance progress counter if appropriate }
|
||||
if (cinfo^.progress <> NIL) and
|
||||
((retcode = JPEG_ROW_COMPLETED) or (retcode = JPEG_REACHED_SOS)) then
|
||||
begin
|
||||
Inc(cinfo^.progress^.pass_counter);
|
||||
if (cinfo^.progress^.pass_counter >= cinfo^.progress^.pass_limit) then
|
||||
begin
|
||||
{ jdmaster underestimated number of scans; ratchet up one scan }
|
||||
Inc(cinfo^.progress^.pass_limit, long(cinfo^.total_iMCU_rows));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
end;
|
||||
cinfo^.output_scan_number := cinfo^.input_scan_number;
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Perform any dummy output passes, and set up for the final pass }
|
||||
jpeg_start_decompress := output_pass_setup(cinfo);
|
||||
end;
|
||||
|
||||
|
||||
{ Set up for an output pass, and perform any dummy pass(es) needed.
|
||||
Common subroutine for jpeg_start_decompress and jpeg_start_output.
|
||||
Entry: global_state := DSTATE_PRESCAN only if previously suspended.
|
||||
Exit: If done, returns TRUE and sets global_state for proper output mode.
|
||||
If suspended, returns FALSE and sets global_state := DSTATE_PRESCAN. }
|
||||
|
||||
{LOCAL}
|
||||
function output_pass_setup (cinfo : j_decompress_ptr) : boolean;
|
||||
var
|
||||
last_scanline : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
begin
|
||||
{ First call: do pass setup }
|
||||
cinfo^.master^.prepare_for_output_pass (cinfo);
|
||||
cinfo^.output_scanline := 0;
|
||||
cinfo^.global_state := DSTATE_PRESCAN;
|
||||
end;
|
||||
{ Loop over any required dummy passes }
|
||||
while (cinfo^.master^.is_dummy_pass) do
|
||||
begin
|
||||
{$ifdef QUANT_2PASS_SUPPORTED}
|
||||
{ Crank through the dummy pass }
|
||||
while (cinfo^.output_scanline < cinfo^.output_height) do
|
||||
begin
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
{ Process some data }
|
||||
last_scanline := cinfo^.output_scanline;
|
||||
cinfo^.main^.process_data (cinfo, JSAMPARRAY(NIL),
|
||||
cinfo^.output_scanline, {var}
|
||||
JDIMENSION(0));
|
||||
if (cinfo^.output_scanline = last_scanline) then
|
||||
begin
|
||||
output_pass_setup := FALSE; { No progress made, must suspend }
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
{ Finish up dummy pass, and set up for another one }
|
||||
cinfo^.master^.finish_output_pass (cinfo);
|
||||
cinfo^.master^.prepare_for_output_pass (cinfo);
|
||||
cinfo^.output_scanline := 0;
|
||||
{$else}
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
{$endif} { QUANT_2PASS_SUPPORTED }
|
||||
end;
|
||||
{ Ready for application to drive output pass through
|
||||
jpeg_read_scanlines or jpeg_read_raw_data. }
|
||||
if cinfo^.raw_data_out then
|
||||
cinfo^.global_state := DSTATE_RAW_OK
|
||||
else
|
||||
cinfo^.global_state := DSTATE_SCANNING;
|
||||
output_pass_setup := TRUE;
|
||||
end;
|
||||
|
||||
|
||||
{ Read some scanlines of data from the JPEG decompressor.
|
||||
|
||||
The return value will be the number of lines actually read.
|
||||
This may be less than the number requested in several cases,
|
||||
including bottom of image, data source suspension, and operating
|
||||
modes that emit multiple scanlines at a time.
|
||||
|
||||
Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||
this likely signals an application programmer error. However,
|
||||
an oversize buffer (max_lines > scanlines remaining) is not an error. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_scanlines (cinfo : j_decompress_ptr;
|
||||
scanlines : JSAMPARRAY;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
row_ctr : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_SCANNING) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.output_scanline >= cinfo^.output_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_read_scanlines := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Process some data }
|
||||
row_ctr := 0;
|
||||
cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, max_lines);
|
||||
Inc(cinfo^.output_scanline, row_ctr);
|
||||
jpeg_read_scanlines := row_ctr;
|
||||
end;
|
||||
|
||||
|
||||
{ Alternate entry point to read raw data.
|
||||
Processes exactly one iMCU row per call, unless suspended. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_read_raw_data (cinfo : j_decompress_ptr;
|
||||
data : JSAMPIMAGE;
|
||||
max_lines : JDIMENSION) : JDIMENSION;
|
||||
var
|
||||
lines_per_iMCU_row : JDIMENSION;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_RAW_OK) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
if (cinfo^.output_scanline >= cinfo^.output_height) then
|
||||
begin
|
||||
WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA);
|
||||
jpeg_read_raw_data := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Call progress monitor hook if present }
|
||||
if (cinfo^.progress <> NIL) then
|
||||
begin
|
||||
cinfo^.progress^.pass_counter := long (cinfo^.output_scanline);
|
||||
cinfo^.progress^.pass_limit := long (cinfo^.output_height);
|
||||
cinfo^.progress^.progress_monitor (j_common_ptr(cinfo));
|
||||
end;
|
||||
|
||||
{ Verify that at least one iMCU row can be returned. }
|
||||
lines_per_iMCU_row := cinfo^.max_v_samp_factor * cinfo^.min_DCT_scaled_size;
|
||||
if (max_lines < lines_per_iMCU_row) then
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE);
|
||||
|
||||
{ Decompress directly into user's buffer. }
|
||||
if (cinfo^.coef^.decompress_data (cinfo, data) = 0) then
|
||||
begin
|
||||
jpeg_read_raw_data := 0; { suspension forced, can do nothing more }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ OK, we processed one iMCU row. }
|
||||
Inc(cinfo^.output_scanline, lines_per_iMCU_row);
|
||||
jpeg_read_raw_data := lines_per_iMCU_row;
|
||||
end;
|
||||
|
||||
|
||||
{ Additional entry points for buffered-image mode. }
|
||||
|
||||
{$ifdef D_MULTISCAN_FILES_SUPPORTED}
|
||||
|
||||
{ Initialize for an output pass in buffered-image mode. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_start_output (cinfo : j_decompress_ptr;
|
||||
scan_number : int) : boolean;
|
||||
begin
|
||||
if (cinfo^.global_state <> DSTATE_BUFIMAGE) and
|
||||
(cinfo^.global_state <> DSTATE_PRESCAN) then
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
{ Limit scan number to valid range }
|
||||
if (scan_number <= 0) then
|
||||
scan_number := 1;
|
||||
if (cinfo^.inputctl^.eoi_reached) and
|
||||
(scan_number > cinfo^.input_scan_number) then
|
||||
scan_number := cinfo^.input_scan_number;
|
||||
cinfo^.output_scan_number := scan_number;
|
||||
{ Perform any dummy output passes, and set up for the real pass }
|
||||
jpeg_start_output := output_pass_setup(cinfo);
|
||||
end;
|
||||
|
||||
|
||||
{ Finish up after an output pass in buffered-image mode.
|
||||
|
||||
Returns FALSE if suspended. The return value need be inspected only if
|
||||
a suspending data source is used. }
|
||||
|
||||
{GLOBAL}
|
||||
function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean;
|
||||
begin
|
||||
if ((cinfo^.global_state = DSTATE_SCANNING) or
|
||||
(cinfo^.global_state = DSTATE_RAW_OK) and cinfo^.buffered_image) then
|
||||
begin
|
||||
{ Terminate this pass. }
|
||||
{ We do not require the whole pass to have been completed. }
|
||||
cinfo^.master^.finish_output_pass (cinfo);
|
||||
cinfo^.global_state := DSTATE_BUFPOST;
|
||||
end
|
||||
else
|
||||
if (cinfo^.global_state <> DSTATE_BUFPOST) then
|
||||
begin
|
||||
{ BUFPOST := repeat call after a suspension, anything else is error }
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
|
||||
end;
|
||||
{ Read markers looking for SOS or EOI }
|
||||
while (cinfo^.input_scan_number <= cinfo^.output_scan_number) and
|
||||
(not cinfo^.inputctl^.eoi_reached) do
|
||||
begin
|
||||
if (cinfo^.inputctl^.consume_input (cinfo) = JPEG_SUSPENDED) then
|
||||
begin
|
||||
jpeg_finish_output := FALSE; { Suspend, come back later }
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
cinfo^.global_state := DSTATE_BUFIMAGE;
|
||||
jpeg_finish_output := TRUE;
|
||||
end;
|
||||
|
||||
{$endif} { D_MULTISCAN_FILES_SUPPORTED }
|
||||
|
||||
end.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,109 +1,109 @@
|
||||
unit imjdct;
|
||||
|
||||
{ Orignal: jdct.h; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This include file contains common declarations for the forward and
|
||||
inverse DCT modules. These declarations are private to the DCT managers
|
||||
(jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
|
||||
The individual DCT algorithms are kept in separate files to ease
|
||||
machine-dependent tuning (e.g., assembly coding). }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg;
|
||||
|
||||
|
||||
{ A forward DCT routine is given a pointer to a work area of type DCTELEM[];
|
||||
the DCT is to be performed in-place in that buffer. Type DCTELEM is int
|
||||
for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
|
||||
implementations use an array of type FAST_FLOAT, instead.)
|
||||
The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
|
||||
The DCT outputs are returned scaled up by a factor of 8; they therefore
|
||||
have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
|
||||
convention improves accuracy in integer implementations and saves some
|
||||
work in floating-point ones.
|
||||
Quantization of the output coefficients is done by jcdctmgr.c. }
|
||||
|
||||
|
||||
{$ifdef BITS_IN_JSAMPLE_IS_8}
|
||||
type
|
||||
DCTELEM = int; { 16 or 32 bits is fine }
|
||||
{$else}
|
||||
type { must have 32 bits }
|
||||
DCTELEM = INT32;
|
||||
{$endif}
|
||||
type
|
||||
jTDctElem = 0..(MaxInt div SizeOf(DCTELEM))-1;
|
||||
DCTELEM_FIELD = array[jTDctElem] of DCTELEM;
|
||||
DCTELEM_FIELD_PTR = ^DCTELEM_FIELD;
|
||||
DCTELEMPTR = ^DCTELEM;
|
||||
|
||||
type
|
||||
forward_DCT_method_ptr = procedure(var data : array of DCTELEM);
|
||||
float_DCT_method_ptr = procedure(var data : array of FAST_FLOAT);
|
||||
|
||||
|
||||
{ An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
|
||||
to an output sample array. The routine must dequantize the input data as
|
||||
well as perform the IDCT; for dequantization, it uses the multiplier table
|
||||
pointed to by compptr->dct_table. The output data is to be placed into the
|
||||
sample array starting at a specified column. (Any row offset needed will
|
||||
be applied to the array pointer before it is passed to the IDCT code.)
|
||||
Note that the number of samples emitted by the IDCT routine is
|
||||
DCT_scaled_size * DCT_scaled_size. }
|
||||
|
||||
|
||||
{ typedef inverse_DCT_method_ptr is declared in jpegint.h }
|
||||
|
||||
|
||||
{ Each IDCT routine has its own ideas about the best dct_table element type. }
|
||||
|
||||
|
||||
type
|
||||
ISLOW_MULT_TYPE = MULTIPLIER; { short or int, whichever is faster }
|
||||
|
||||
{$ifdef BITS_IN_JSAMPLE_IS_8}
|
||||
type
|
||||
IFAST_MULT_TYPE = MULTIPLIER; { 16 bits is OK, use short if faster }
|
||||
const
|
||||
IFAST_SCALE_BITS = 2; { fractional bits in scale factors }
|
||||
{$else}
|
||||
type
|
||||
IFAST_MULT_TYPE = INT32; { need 32 bits for scaled quantizers }
|
||||
const
|
||||
IFAST_SCALE_BITS = 13; { fractional bits in scale factors }
|
||||
{$endif}
|
||||
type
|
||||
FLOAT_MULT_TYPE = FAST_FLOAT; { preferred floating type }
|
||||
|
||||
const
|
||||
RANGE_MASK = (MAXJSAMPLE * 4 + 3); { 2 bits wider than legal samples }
|
||||
|
||||
type
|
||||
jTMultType = 0..(MaxInt div SizeOf(ISLOW_MULT_TYPE))-1;
|
||||
ISLOW_MULT_TYPE_FIELD = array[jTMultType] of ISLOW_MULT_TYPE;
|
||||
ISLOW_MULT_TYPE_FIELD_PTR = ^ISLOW_MULT_TYPE_FIELD;
|
||||
ISLOW_MULT_TYPE_PTR = ^ISLOW_MULT_TYPE;
|
||||
|
||||
jTFloatType = 0..(MaxInt div SizeOf(FLOAT_MULT_TYPE))-1;
|
||||
FLOAT_MULT_TYPE_FIELD = array[jTFloatType] of FLOAT_MULT_TYPE;
|
||||
FLOAT_MULT_TYPE_FIELD_PTR = ^FLOAT_MULT_TYPE_FIELD;
|
||||
FLOAT_MULT_TYPE_PTR = ^FLOAT_MULT_TYPE;
|
||||
|
||||
jTFastType = 0..(MaxInt div SizeOf(IFAST_MULT_TYPE))-1;
|
||||
IFAST_MULT_TYPE_FIELD = array[jTFastType] of IFAST_MULT_TYPE;
|
||||
IFAST_MULT_TYPE_FIELD_PTR = ^IFAST_MULT_TYPE_FIELD;
|
||||
IFAST_MULT_TYPE_PTR = ^IFAST_MULT_TYPE;
|
||||
|
||||
type
|
||||
jTFastFloat = 0..(MaxInt div SizeOf(FAST_FLOAT))-1;
|
||||
FAST_FLOAT_FIELD = array[jTFastFloat] of FAST_FLOAT;
|
||||
FAST_FLOAT_FIELD_PTR = ^FAST_FLOAT_FIELD;
|
||||
FAST_FLOAT_PTR = ^FAST_FLOAT;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
unit imjdct;
|
||||
|
||||
{ Orignal: jdct.h; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This include file contains common declarations for the forward and
|
||||
inverse DCT modules. These declarations are private to the DCT managers
|
||||
(jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
|
||||
The individual DCT algorithms are kept in separate files to ease
|
||||
machine-dependent tuning (e.g., assembly coding). }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg;
|
||||
|
||||
|
||||
{ A forward DCT routine is given a pointer to a work area of type DCTELEM[];
|
||||
the DCT is to be performed in-place in that buffer. Type DCTELEM is int
|
||||
for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
|
||||
implementations use an array of type FAST_FLOAT, instead.)
|
||||
The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
|
||||
The DCT outputs are returned scaled up by a factor of 8; they therefore
|
||||
have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
|
||||
convention improves accuracy in integer implementations and saves some
|
||||
work in floating-point ones.
|
||||
Quantization of the output coefficients is done by jcdctmgr.c. }
|
||||
|
||||
|
||||
{$ifdef BITS_IN_JSAMPLE_IS_8}
|
||||
type
|
||||
DCTELEM = int; { 16 or 32 bits is fine }
|
||||
{$else}
|
||||
type { must have 32 bits }
|
||||
DCTELEM = INT32;
|
||||
{$endif}
|
||||
type
|
||||
jTDctElem = 0..(MaxInt div SizeOf(DCTELEM))-1;
|
||||
DCTELEM_FIELD = array[jTDctElem] of DCTELEM;
|
||||
DCTELEM_FIELD_PTR = ^DCTELEM_FIELD;
|
||||
DCTELEMPTR = ^DCTELEM;
|
||||
|
||||
type
|
||||
forward_DCT_method_ptr = procedure(var data : array of DCTELEM);
|
||||
float_DCT_method_ptr = procedure(var data : array of FAST_FLOAT);
|
||||
|
||||
|
||||
{ An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
|
||||
to an output sample array. The routine must dequantize the input data as
|
||||
well as perform the IDCT; for dequantization, it uses the multiplier table
|
||||
pointed to by compptr->dct_table. The output data is to be placed into the
|
||||
sample array starting at a specified column. (Any row offset needed will
|
||||
be applied to the array pointer before it is passed to the IDCT code.)
|
||||
Note that the number of samples emitted by the IDCT routine is
|
||||
DCT_scaled_size * DCT_scaled_size. }
|
||||
|
||||
|
||||
{ typedef inverse_DCT_method_ptr is declared in jpegint.h }
|
||||
|
||||
|
||||
{ Each IDCT routine has its own ideas about the best dct_table element type. }
|
||||
|
||||
|
||||
type
|
||||
ISLOW_MULT_TYPE = MULTIPLIER; { short or int, whichever is faster }
|
||||
|
||||
{$ifdef BITS_IN_JSAMPLE_IS_8}
|
||||
type
|
||||
IFAST_MULT_TYPE = MULTIPLIER; { 16 bits is OK, use short if faster }
|
||||
const
|
||||
IFAST_SCALE_BITS = 2; { fractional bits in scale factors }
|
||||
{$else}
|
||||
type
|
||||
IFAST_MULT_TYPE = INT32; { need 32 bits for scaled quantizers }
|
||||
const
|
||||
IFAST_SCALE_BITS = 13; { fractional bits in scale factors }
|
||||
{$endif}
|
||||
type
|
||||
FLOAT_MULT_TYPE = FAST_FLOAT; { preferred floating type }
|
||||
|
||||
const
|
||||
RANGE_MASK = (MAXJSAMPLE * 4 + 3); { 2 bits wider than legal samples }
|
||||
|
||||
type
|
||||
jTMultType = 0..(MaxInt div SizeOf(ISLOW_MULT_TYPE))-1;
|
||||
ISLOW_MULT_TYPE_FIELD = array[jTMultType] of ISLOW_MULT_TYPE;
|
||||
ISLOW_MULT_TYPE_FIELD_PTR = ^ISLOW_MULT_TYPE_FIELD;
|
||||
ISLOW_MULT_TYPE_PTR = ^ISLOW_MULT_TYPE;
|
||||
|
||||
jTFloatType = 0..(MaxInt div SizeOf(FLOAT_MULT_TYPE))-1;
|
||||
FLOAT_MULT_TYPE_FIELD = array[jTFloatType] of FLOAT_MULT_TYPE;
|
||||
FLOAT_MULT_TYPE_FIELD_PTR = ^FLOAT_MULT_TYPE_FIELD;
|
||||
FLOAT_MULT_TYPE_PTR = ^FLOAT_MULT_TYPE;
|
||||
|
||||
jTFastType = 0..(MaxInt div SizeOf(IFAST_MULT_TYPE))-1;
|
||||
IFAST_MULT_TYPE_FIELD = array[jTFastType] of IFAST_MULT_TYPE;
|
||||
IFAST_MULT_TYPE_FIELD_PTR = ^IFAST_MULT_TYPE_FIELD;
|
||||
IFAST_MULT_TYPE_PTR = ^IFAST_MULT_TYPE;
|
||||
|
||||
type
|
||||
jTFastFloat = 0..(MaxInt div SizeOf(FAST_FLOAT))-1;
|
||||
FAST_FLOAT_FIELD = array[jTFastFloat] of FAST_FLOAT;
|
||||
FAST_FLOAT_FIELD_PTR = ^FAST_FLOAT_FIELD;
|
||||
FAST_FLOAT_PTR = ^FAST_FLOAT;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
||||
@ -1,330 +1,328 @@
|
||||
unit imjddctmgr;
|
||||
|
||||
{ Original : jddctmgr.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file contains the inverse-DCT management logic.
|
||||
This code selects a particular IDCT implementation to be used,
|
||||
and it performs related housekeeping chores. No code in this file
|
||||
is executed per IDCT step, only during output pass setup.
|
||||
|
||||
Note that the IDCT routines are responsible for performing coefficient
|
||||
dequantization as well as the IDCT proper. This module sets up the
|
||||
dequantization multiplier table needed by the IDCT routine. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
{$N+}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjdct, { Private declarations for DCT subsystem }
|
||||
imjidctfst,
|
||||
{$IFDEF BASM}
|
||||
imjidctasm,
|
||||
{$ELSE}
|
||||
imjidctint,
|
||||
{$ENDIF}
|
||||
imjidctflt,
|
||||
imjidctred;
|
||||
|
||||
|
||||
|
||||
{ Initialize IDCT manager. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_inverse_dct (cinfo : j_decompress_ptr);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ The decompressor input side (jdinput.c) saves away the appropriate
|
||||
quantization table for each component at the start of the first scan
|
||||
involving that component. (This is necessary in order to correctly
|
||||
decode files that reuse Q-table slots.)
|
||||
When we are ready to make an output pass, the saved Q-table is converted
|
||||
to a multiplier table that will actually be used by the IDCT routine.
|
||||
The multiplier table contents are IDCT-method-dependent. To support
|
||||
application changes in IDCT method between scans, we can remake the
|
||||
multiplier tables if necessary.
|
||||
In buffered-image mode, the first output pass may occur before any data
|
||||
has been seen for some components, and thus before their Q-tables have
|
||||
been saved away. To handle this case, multiplier tables are preset
|
||||
to zeroes; the result of the IDCT will be a neutral gray level. }
|
||||
|
||||
|
||||
{ Private subobject for this module }
|
||||
|
||||
type
|
||||
my_idct_ptr = ^my_idct_controller;
|
||||
my_idct_controller = record
|
||||
pub : jpeg_inverse_dct; { public fields }
|
||||
|
||||
{ This array contains the IDCT method code that each multiplier table
|
||||
is currently set up for, or -1 if it's not yet set up.
|
||||
The actual multiplier tables are pointed to by dct_table in the
|
||||
per-component comp_info structures. }
|
||||
|
||||
cur_method : array[0..MAX_COMPONENTS-1] of int;
|
||||
end; {my_idct_controller;}
|
||||
|
||||
|
||||
{ Allocated multiplier tables: big enough for any supported variant }
|
||||
|
||||
type
|
||||
multiplier_table = record
|
||||
case byte of
|
||||
0:(islow_array : array[0..DCTSIZE2-1] of ISLOW_MULT_TYPE);
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
1:(ifast_array : array[0..DCTSIZE2-1] of IFAST_MULT_TYPE);
|
||||
{$endif}
|
||||
{$ifdef DCT_FLOAT_SUPPORTED}
|
||||
2:(float_array : array[0..DCTSIZE2-1] of FLOAT_MULT_TYPE);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
|
||||
{ The current scaled-IDCT routines require ISLOW-style multiplier tables,
|
||||
so be sure to compile that code if either ISLOW or SCALING is requested. }
|
||||
|
||||
{$ifdef DCT_ISLOW_SUPPORTED}
|
||||
{$define PROVIDE_ISLOW_TABLES}
|
||||
{$else}
|
||||
{$ifdef IDCT_SCALING_SUPPORTED}
|
||||
{$define PROVIDE_ISLOW_TABLES}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
|
||||
{ Prepare for an output pass.
|
||||
Here we select the proper IDCT routine for each component and build
|
||||
a matching multiplier table. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass (cinfo : j_decompress_ptr);
|
||||
var
|
||||
idct : my_idct_ptr;
|
||||
ci, i : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
method : J_DCT_METHOD;
|
||||
method_ptr : inverse_DCT_method_ptr;
|
||||
qtbl : JQUANT_TBL_PTR;
|
||||
{$ifdef PROVIDE_ISLOW_TABLES}
|
||||
var
|
||||
ismtbl : ISLOW_MULT_TYPE_FIELD_PTR;
|
||||
{$endif}
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
const
|
||||
CONST_BITS = 14;
|
||||
const
|
||||
aanscales : array[0..DCTSIZE2-1] of INT16 =
|
||||
({ precomputed values scaled up by 14 bits }
|
||||
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
|
||||
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
|
||||
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
|
||||
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
|
||||
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
|
||||
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247);
|
||||
var
|
||||
ifmtbl : IFAST_MULT_TYPE_FIELD_PTR;
|
||||
{SHIFT_TEMPS}
|
||||
|
||||
{ Descale and correctly round an INT32 value that's scaled by N bits.
|
||||
We assume RIGHT_SHIFT rounds towards minus infinity, so adding
|
||||
the fudge factor is correct for either sign of X. }
|
||||
|
||||
function DESCALE(x : INT32; n : int) : INT32;
|
||||
var
|
||||
shift_temp : INT32;
|
||||
begin
|
||||
{$ifdef RIGHT_SHIFT_IS_UNSIGNED}
|
||||
shift_temp := x + (INT32(1) shl (n-1));
|
||||
if shift_temp < 0 then
|
||||
Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n))
|
||||
else
|
||||
Descale := (shift_temp shr n);
|
||||
{$else}
|
||||
Descale := (x + (INT32(1) shl (n-1)) shr n;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
{$endif}
|
||||
{$ifdef DCT_FLOAT_SUPPORTED}
|
||||
const
|
||||
aanscalefactor : array[0..DCTSIZE-1] of double =
|
||||
(1.0, 1.387039845, 1.306562965, 1.175875602,
|
||||
1.0, 0.785694958, 0.541196100, 0.275899379);
|
||||
var
|
||||
fmtbl : FLOAT_MULT_TYPE_FIELD_PTR;
|
||||
row, col : int;
|
||||
{$endif}
|
||||
begin
|
||||
idct := my_idct_ptr (cinfo^.idct);
|
||||
method := J_DCT_METHOD(0);
|
||||
method_ptr := NIL;
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
{ Select the proper IDCT routine for this component's scaling }
|
||||
case (compptr^.DCT_scaled_size) of
|
||||
{$ifdef IDCT_SCALING_SUPPORTED}
|
||||
1:begin
|
||||
method_ptr := jpeg_idct_1x1;
|
||||
method := JDCT_ISLOW; { jidctred uses islow-style table }
|
||||
end;
|
||||
2:begin
|
||||
method_ptr := jpeg_idct_2x2;
|
||||
method := JDCT_ISLOW; { jidctred uses islow-style table }
|
||||
end;
|
||||
4:begin
|
||||
method_ptr := jpeg_idct_4x4;
|
||||
method := JDCT_ISLOW; { jidctred uses islow-style table }
|
||||
end;
|
||||
{$endif}
|
||||
DCTSIZE:
|
||||
case (cinfo^.dct_method) of
|
||||
{$ifdef DCT_ISLOW_SUPPORTED}
|
||||
JDCT_ISLOW:
|
||||
begin
|
||||
method_ptr := @jpeg_idct_islow;
|
||||
method := JDCT_ISLOW;
|
||||
end;
|
||||
{$endif}
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
JDCT_IFAST:
|
||||
begin
|
||||
method_ptr := @jpeg_idct_ifast;
|
||||
method := JDCT_IFAST;
|
||||
end;
|
||||
{$endif}
|
||||
{$ifdef DCT_FLOAT_SUPPORTED}
|
||||
JDCT_FLOAT:
|
||||
begin
|
||||
method_ptr := @jpeg_idct_float;
|
||||
method := JDCT_FLOAT;
|
||||
end;
|
||||
{$endif}
|
||||
else
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
end;
|
||||
else
|
||||
ERREXIT1(j_common_ptr(cinfo), JERR_BAD_DCTSIZE, compptr^.DCT_scaled_size);
|
||||
end;
|
||||
idct^.pub.inverse_DCT[ci] := method_ptr;
|
||||
{ Create multiplier table from quant table.
|
||||
However, we can skip this if the component is uninteresting
|
||||
or if we already built the table. Also, if no quant table
|
||||
has yet been saved for the component, we leave the
|
||||
multiplier table all-zero; we'll be reading zeroes from the
|
||||
coefficient controller's buffer anyway. }
|
||||
|
||||
if (not compptr^.component_needed) or (idct^.cur_method[ci] = int(method)) then
|
||||
continue;
|
||||
qtbl := compptr^.quant_table;
|
||||
if (qtbl = NIL) then { happens if no data yet for component }
|
||||
continue;
|
||||
idct^.cur_method[ci] := int(method);
|
||||
case (method) of
|
||||
{$ifdef PROVIDE_ISLOW_TABLES}
|
||||
JDCT_ISLOW:
|
||||
begin
|
||||
{ For LL&M IDCT method, multipliers are equal to raw quantization
|
||||
coefficients, but are stored as ints to ensure access efficiency. }
|
||||
|
||||
ismtbl := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table);
|
||||
for i := 0 to pred(DCTSIZE2) do
|
||||
begin
|
||||
ismtbl^[i] := ISLOW_MULT_TYPE (qtbl^.quantval[i]);
|
||||
end;
|
||||
end;
|
||||
{$endif}
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
JDCT_IFAST:
|
||||
begin
|
||||
{ For AA&N IDCT method, multipliers are equal to quantization
|
||||
coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||
scalefactor[0] := 1
|
||||
scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7
|
||||
For integer operation, the multiplier table is to be scaled by
|
||||
IFAST_SCALE_BITS. }
|
||||
|
||||
ifmtbl := IFAST_MULT_TYPE_FIELD_PTR (compptr^.dct_table);
|
||||
|
||||
for i := 0 to pred(DCTSIZE2) do
|
||||
begin
|
||||
ifmtbl^[i] := IFAST_MULT_TYPE(
|
||||
DESCALE( INT32 (qtbl^.quantval[i]) * INT32 (aanscales[i]),
|
||||
CONST_BITS-IFAST_SCALE_BITS) );
|
||||
end;
|
||||
end;
|
||||
{$endif}
|
||||
{$ifdef DCT_FLOAT_SUPPORTED}
|
||||
JDCT_FLOAT:
|
||||
begin
|
||||
{ For float AA&N IDCT method, multipliers are equal to quantization
|
||||
coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||
scalefactor[0] := 1
|
||||
scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7 }
|
||||
|
||||
fmtbl := FLOAT_MULT_TYPE_FIELD_PTR(compptr^.dct_table);
|
||||
|
||||
i := 0;
|
||||
for row := 0 to pred(DCTSIZE) do
|
||||
begin
|
||||
for col := 0 to pred(DCTSIZE) do
|
||||
begin
|
||||
fmtbl^[i] := {FLOAT_MULT_TYPE} (
|
||||
{double} qtbl^.quantval[i] *
|
||||
aanscalefactor[row] * aanscalefactor[col] );
|
||||
Inc(i);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$endif}
|
||||
else
|
||||
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
|
||||
break;
|
||||
end;
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Initialize IDCT manager. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_inverse_dct (cinfo : j_decompress_ptr);
|
||||
var
|
||||
idct : my_idct_ptr;
|
||||
ci : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
begin
|
||||
idct := my_idct_ptr(
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(my_idct_controller)) );
|
||||
cinfo^.idct := jpeg_inverse_dct_ptr (idct);
|
||||
idct^.pub.start_pass := start_pass;
|
||||
|
||||
compptr := jpeg_component_info_ptr(cinfo^.comp_info);
|
||||
for ci := 0 to pred(cinfo^.num_components) do
|
||||
begin
|
||||
{ Allocate and pre-zero a multiplier table for each component }
|
||||
compptr^.dct_table :=
|
||||
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
|
||||
SIZEOF(multiplier_table));
|
||||
MEMZERO(compptr^.dct_table, SIZEOF(multiplier_table));
|
||||
{ Mark multiplier table not yet set up for any method }
|
||||
idct^.cur_method[ci] := -1;
|
||||
Inc(compptr);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
unit imjddctmgr;
|
||||
|
||||
{ Original : jddctmgr.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
|
||||
|
||||
{ This file contains the inverse-DCT management logic.
|
||||
This code selects a particular IDCT implementation to be used,
|
||||
and it performs related housekeeping chores. No code in this file
|
||||
is executed per IDCT step, only during output pass setup.
|
||||
|
||||
Note that the IDCT routines are responsible for performing coefficient
|
||||
dequantization as well as the IDCT proper. This module sets up the
|
||||
dequantization multiplier table needed by the IDCT routine. }
|
||||
|
||||
interface
|
||||
|
||||
{$I imjconfig.inc}
|
||||
|
||||
uses
|
||||
imjmorecfg,
|
||||
imjinclude,
|
||||
imjdeferr,
|
||||
imjerror,
|
||||
imjpeglib,
|
||||
imjdct, { Private declarations for DCT subsystem }
|
||||
imjidctfst,
|
||||
{$IFDEF BASM}
|
||||
imjidctasm,
|
||||
{$ELSE}
|
||||
imjidctint,
|
||||
{$ENDIF}
|
||||
imjidctflt,
|
||||
imjidctred;
|
||||
|
||||
|
||||
|
||||
{ Initialize IDCT manager. }
|
||||
|
||||
{GLOBAL}
|
||||
procedure jinit_inverse_dct (cinfo : j_decompress_ptr);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ The decompressor input side (jdinput.c) saves away the appropriate
|
||||
quantization table for each component at the start of the first scan
|
||||
involving that component. (This is necessary in order to correctly
|
||||
decode files that reuse Q-table slots.)
|
||||
When we are ready to make an output pass, the saved Q-table is converted
|
||||
to a multiplier table that will actually be used by the IDCT routine.
|
||||
The multiplier table contents are IDCT-method-dependent. To support
|
||||
application changes in IDCT method between scans, we can remake the
|
||||
multiplier tables if necessary.
|
||||
In buffered-image mode, the first output pass may occur before any data
|
||||
has been seen for some components, and thus before their Q-tables have
|
||||
been saved away. To handle this case, multiplier tables are preset
|
||||
to zeroes; the result of the IDCT will be a neutral gray level. }
|
||||
|
||||
|
||||
{ Private subobject for this module }
|
||||
|
||||
type
|
||||
my_idct_ptr = ^my_idct_controller;
|
||||
my_idct_controller = record
|
||||
pub : jpeg_inverse_dct; { public fields }
|
||||
|
||||
{ This array contains the IDCT method code that each multiplier table
|
||||
is currently set up for, or -1 if it's not yet set up.
|
||||
The actual multiplier tables are pointed to by dct_table in the
|
||||
per-component comp_info structures. }
|
||||
|
||||
cur_method : array[0..MAX_COMPONENTS-1] of int;
|
||||
end; {my_idct_controller;}
|
||||
|
||||
|
||||
{ Allocated multiplier tables: big enough for any supported variant }
|
||||
|
||||
type
|
||||
multiplier_table = record
|
||||
case byte of
|
||||
0:(islow_array : array[0..DCTSIZE2-1] of ISLOW_MULT_TYPE);
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
1:(ifast_array : array[0..DCTSIZE2-1] of IFAST_MULT_TYPE);
|
||||
{$endif}
|
||||
{$ifdef DCT_FLOAT_SUPPORTED}
|
||||
2:(float_array : array[0..DCTSIZE2-1] of FLOAT_MULT_TYPE);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
|
||||
{ The current scaled-IDCT routines require ISLOW-style multiplier tables,
|
||||
so be sure to compile that code if either ISLOW or SCALING is requested. }
|
||||
|
||||
{$ifdef DCT_ISLOW_SUPPORTED}
|
||||
{$define PROVIDE_ISLOW_TABLES}
|
||||
{$else}
|
||||
{$ifdef IDCT_SCALING_SUPPORTED}
|
||||
{$define PROVIDE_ISLOW_TABLES}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
|
||||
{ Prepare for an output pass.
|
||||
Here we select the proper IDCT routine for each component and build
|
||||
a matching multiplier table. }
|
||||
|
||||
{METHODDEF}
|
||||
procedure start_pass (cinfo : j_decompress_ptr);
|
||||
var
|
||||
idct : my_idct_ptr;
|
||||
ci, i : int;
|
||||
compptr : jpeg_component_info_ptr;
|
||||
method : J_DCT_METHOD;
|
||||
method_ptr : inverse_DCT_method_ptr;
|
||||
qtbl : JQUANT_TBL_PTR;
|
||||
{$ifdef PROVIDE_ISLOW_TABLES}
|
||||
var
|
||||
ismtbl : ISLOW_MULT_TYPE_FIELD_PTR;
|
||||
{$endif}
|
||||
{$ifdef DCT_IFAST_SUPPORTED}
|
||||
const
|
||||
CONST_BITS = 14;
|
||||
const
|
||||
aanscales : array[0..DCTSIZE2-1] of INT16 =
|
||||
({ precomputed values scaled up by 14 bits }
|
||||
16384, | ||||