D
D
Daniil Bakalin2015-10-20 01:05:25
Delphi
Daniil Bakalin, 2015-10-20 01:05:25

How to open 64-bit png with delphi or c#?

Good afternoon!
There was a task to open a 64-bit (16 bit per channel) .png file in my program.
Process it using a tricky algorithm and save it as a regular 32 bit (8 bit per channel) .png file.
The problem is little experience, but the task needs to be solved...
I managed to find that in dephi this can be done through GDI +, but the examples from the network either do not work at all, or require old libraries and, as a result, do not work either.
They write that it is easier to do this using C #. I have even less experience in it, so it's not at all clear where to dig ...
I would be very grateful for an example or direction to search.
Ready for a paid consultation (I'll post the solution here for everyone).
The format of the source is not important, I can convert to anything.
In extreme cases, you can not read the alpha channel (i.e. read a 48-bit file).
I've already gone so far as to write a macro to move the mouse in photoshop and read the pixels below it, but photoshop doesn't show the value of 16-bit colors...

Answer the question

In order to leave comments, you need to log in

3 answer(s)
X
x128, 2015-10-28
@Quiensabe

Sketched a small example on Delphi. The key point of ExtraScanline .

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math,
  Vcl.Imaging.PNGImage;

type
  TRGB = record
    r,g,b: single;
  end;
  TIMG = record
    xmax, ymax: integer;
    data: array of array of TRGB;
  end;

function LoadPNG48(var img: TIMG; const fname: string): boolean;
var
  png: TPNGImage;
  x,y: integer;
  scan,extra: pRGBLine;
begin
  png:=TPNGImage.Create;
  png.LoadFromFile(fname);
  result:=png.Header.BitDepth=16;
  if result then begin
    img.xmax:=png.Width;
    img.ymax:=png.Height;
    SetLength(img.data, png.Height, png.Width);
    for y:=0 to img.ymax-1 do begin
      scan:=png.Scanline[y];
      extra:=png.ExtraScanline[y];
      for x:=0 to img.xmax-1 do begin
        img.data[y,x].r:=(scan[x].rgbtRed shl 8 + extra[x].rgbtRed) / 65535;
        img.data[y,x].g:=(scan[x].rgbtGreen shl 8 + extra[x].rgbtGreen) / 65535;
        img.data[y,x].b:=(scan[x].rgbtBlue shl 8 + extra[x].rgbtBlue) / 65535;
      end;
    end;
  end;
  png.Free;
end;

procedure SavePNG24(var img: TIMG; const fname: string);
var
  png: TPNGImage;
  x,y: integer;
  scan: pRGBLine;
begin
  png:=TPNGImage.CreateBlank(COLOR_RGB, 8, img.xmax, img.ymax);
  for y:=0 to img.ymax-1 do begin
    scan:=png.Scanline[y];
    for x:=0 to img.xmax-1 do begin
      scan[x].rgbtRed:=round(img.data[y,x].r*255);
      scan[x].rgbtGreen:=round(img.data[y,x].g*255);
      scan[x].rgbtBlue:=round(img.data[y,x].b*255);
    end;
  end;
  png.SaveToFile(fname);
end;

var
  img: TIMG;
  x,y: integer;
begin
  if LoadPNG48(img, 'test48.png') then begin
    for y:=0 to img.ymax-1 do begin
      for x:=0 to img.xmax-1 do begin
        img.data[y,x].r:=power(img.data[y,x].r, 1 / 2.2);
        img.data[y,x].g:=power(img.data[y,x].g, 1 / 2.2);
        img.data[y,x].b:=power(img.data[y,x].b, 1 / 2.2);
      end;
    end;
    SavePNG24(img, 'test24.png');
  end;
end.

H
helvit, 2015-10-20
@helvit

Here's the PNG specification www.w3.org/TR/PNG
Everything you need is there.
And here is an example from MS https://msdn.microsoft.com/ru-ru/library/aa970062%...

A
Alexander Taratin, 2015-10-20
@Taraflex

freeimage.sourceforge.net/download.html
There are wrappers for both c# and delphi

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question