There are some Jpg images which Delphi doesn\'t seem to like. It appears to be specific with the files I\'m loading. And the procedure is simple - a) load Jpg image to
Prompted by your other question, here's some code to load a JPG file to a bitmap and conditionally apply a correction to the resulting bitmap. Please note this works for your Brown.JPG image, but I have no idea what's in those first 18 bytes, so I have no idea if this is going to work long-term or not. I'd personally prefer the use of ready-made, known-to-work, widely used library. Alternatively I'd use David's idea of using WIC if available and reverting to this style of hacky code if not available.
Here's the full unit code, so you can see all the used units. The form only expects a single TImage named Image1 on the form, so you can create your form first, put the TImage there, then switch to source code view and copy-paste my code over the Delphi-produced code.
The code opens the file with the JPG image, and loads it into a TJpgImage. It then compares the first 18 bytes of the file to a known marker. If there's a match it applies a transformation to each and every pixel of the produced bitmap. Because writing the actual marker constants is difficult there's a routine (CopyConstToClipboard) that takes the bytes from the file, transforms them into a Delphi-style constant and copies that to the clipboard. When you find a new file that doesn't work you should use this routine to prepare a new constant.
unit Unit9;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Jpeg, Clipbrd;
type
TForm9 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form9: TForm9;
implementation
{$R *.dfm}
type
TRGB_Pixel = packed record
B1: Byte;
B2: Byte;
B3: Byte;
end;
TScanLine = array[0..(System.MaxInt div SizeOf(TRGB_Pixel))-1] of TRGB_Pixel;
PScanLine = ^TScanLine;
procedure CopyConstToClipboard(const FB:array of byte);
var s: string;
i: Integer;
begin
s := 'Name: array[0..' + IntToStr(High(FB)) + '] of Byte = ($' + IntToHex(FB[0], 2);
for i:=1 to High(FB) do
s := s + ', $' + IntToHex(FB[i],2);
s := s + ');';
Clipboard.AsText := s;
end;
function LoadJpegIntoBitmap(const FileName:string): TBitmap;
var F: TFileStream;
Jpg: TJPEGImage;
FirstBytes:array[0..17] of Byte;
y,x: Integer;
ScanLine: PScanLine;
const Marker_1: array[0..17] of Byte = ($FF, $D8, $FF, $EE, $00, $0E, $41, $64, $6F, $62, $65, $00, $64, $00, $00, $00, $00, $00);
procedure SwapBytes(var A, B: Byte);
var T: Byte;
begin
T := A;
A := B;
B := T;
end;
begin
F := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Jpg := TJPEGImage.Create;
try
Jpg.LoadFromStream(F);
F.Position := 0;
F.Read(FirstBytes, SizeOf(FirstBytes));
// CopyConstToClipboard(FirstBytes); // Uncomment this to copy those first bytes to cliboard
Result := TBitmap.Create;
Result.Assign(Jpg);
if (Result.PixelFormat = pf24bit) and CompareMem(@Marker_1, @FirstBytes, SizeOf(FirstBytes)) then
begin
for y:=0 to Result.Height-1 do
begin
ScanLine := Result.ScanLine[y];
for x:=0 to Result.Width-1 do
begin
SwapBytes(ScanLine[x].B1, ScanLine[x].B3);
end;
end;
end;
finally Jpg.Free;
end;
finally F.Free;
end;
end;
procedure TForm9.FormCreate(Sender: TObject);
var B: TBitmap;
begin
B := LoadJpegIntoBitmap('C:\Users\Cosmin Prund\Downloads\ABrownImage.jpg');
try
Image1.Picture.Assign(B);
finally B.Free;
end;
end;
end.