Skip to content

Commit 78c2c24

Browse files
committed
First code commin
1 parent d4be968 commit 78c2c24

20 files changed

+1157
-0
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bin/
2+
obj/

Diff for: testopj/BMPGray16.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace testopj
4+
{
5+
public class BMPGray16
6+
{
7+
public BMPGray16(int w, int h, int actualBPP, ushort[] pixels)
8+
{
9+
W = w;
10+
H = h;
11+
ActualBPP = actualBPP;
12+
Pixels = pixels;
13+
}
14+
15+
public int W { get; private set; }
16+
17+
public int H { get; private set; }
18+
19+
public int ActualBPP { get; private set; }
20+
21+
public ushort[] Pixels { get; private set; }
22+
}
23+
}

Diff for: testopj/OPJDecode.cs

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using OpenJPEG;
4+
5+
namespace testopj
6+
{
7+
public class OPJDecode
8+
{
9+
private readonly OpenJPEGFunctions.opj_msg_callback _cbInfo;
10+
private readonly OpenJPEGFunctions.opj_msg_callback _cbWarning;
11+
private readonly OpenJPEGFunctions.opj_msg_callback _cbError;
12+
private readonly OpenJPEGFunctions.opj_stream_free_user_data_fn _freeUserDataFn;
13+
private readonly OpenJPEGFunctions.opj_stream_read_fn _readFn;
14+
private readonly OpenJPEGFunctions.opj_stream_skip_fn _skipFn;
15+
private readonly OpenJPEGFunctions.opj_stream_seek_fn _seekFn;
16+
17+
private byte[] _image;
18+
private int _offset;
19+
20+
public OPJDecode()
21+
{
22+
_cbInfo = new OpenJPEGFunctions.opj_msg_callback(MsgInfo);
23+
_cbWarning = new OpenJPEGFunctions.opj_msg_callback(MsgWarning);
24+
_cbError = new OpenJPEGFunctions.opj_msg_callback(MsgError);
25+
_freeUserDataFn = new OpenJPEGFunctions.opj_stream_free_user_data_fn(FreeUserData);
26+
_readFn = new OpenJPEGFunctions.opj_stream_read_fn(Read);
27+
_skipFn = new OpenJPEGFunctions.opj_stream_skip_fn(Skip);
28+
_seekFn = new OpenJPEGFunctions.opj_stream_seek_fn(Seek);
29+
}
30+
31+
public BMPGray16 DecodeGray16(byte[] bin)
32+
{
33+
_image = bin;
34+
_offset = 0;
35+
36+
var opjStream = OpenJPEGFunctions.opj_stream_default_create((int)OpenJPEGBool.True);
37+
var opjCodec = OpenJPEGFunctions.opj_create_decompress((int)OpenJPEGCodecFormat.JP2);
38+
var headerPtrMem = Marshal.AllocHGlobal(IntPtr.Size);
39+
Marshal.WriteIntPtr(headerPtrMem, IntPtr.Zero);
40+
41+
try
42+
{
43+
OpenJPEGFunctions.opj_set_info_handler(opjCodec, _cbInfo, IntPtr.Zero);
44+
OpenJPEGFunctions.opj_set_warning_handler(opjCodec, _cbWarning, IntPtr.Zero);
45+
OpenJPEGFunctions.opj_set_error_handler(opjCodec, _cbError, IntPtr.Zero);
46+
OpenJPEGFunctions.opj_stream_set_read_function(opjStream, _readFn);
47+
OpenJPEGFunctions.opj_stream_set_skip_function(opjStream, _skipFn);
48+
OpenJPEGFunctions.opj_stream_set_seek_function(opjStream, _seekFn);
49+
50+
OpenJPEGFunctions.opj_stream_set_user_data(opjStream, IntPtr.Zero, _freeUserDataFn);
51+
OpenJPEGFunctions.opj_stream_set_user_data_length(opjStream, (ulong)_image.Length);
52+
53+
if (OpenJPEGFunctions.opj_read_header(opjStream, opjCodec, headerPtrMem) != (int)OpenJPEGBool.True)
54+
throw new OPJException();
55+
56+
var headerPtr = Marshal.ReadIntPtr(headerPtrMem);
57+
58+
try
59+
{
60+
if (OpenJPEGFunctions.opj_decode(opjCodec, opjStream, headerPtr) != (int)OpenJPEGBool.True)
61+
throw new OPJException();
62+
63+
var img = Marshal.PtrToStructure<OpenJPEGImage>(headerPtr);
64+
var imgComp = Marshal.PtrToStructure<OpenJPEGImageComp>(img.comps);
65+
66+
var imgData16 = new ushort[imgComp.w * imgComp.h];
67+
68+
unsafe
69+
{
70+
var p = (byte*)imgComp.data;
71+
for (var n = 0; n < imgData16.Length; ++n)
72+
{
73+
int v = *p;
74+
++p;
75+
v |= *p << 8;
76+
p += 3;
77+
78+
v <<= (16 - (int)imgComp.prec);
79+
imgData16[n] = (ushort)v;
80+
}
81+
}
82+
83+
return new BMPGray16((int)imgComp.w, (int)imgComp.h, (int)imgComp.prec, imgData16);
84+
}
85+
finally
86+
{
87+
OpenJPEGFunctions.opj_image_destroy(headerPtr);
88+
}
89+
}
90+
finally
91+
{
92+
Marshal.FreeHGlobal(headerPtrMem);
93+
OpenJPEGFunctions.opj_destroy_codec(opjCodec);
94+
OpenJPEGFunctions.opj_stream_destroy(opjStream);
95+
}
96+
}
97+
98+
private void MsgInfo(string msg, IntPtr clientData)
99+
{
100+
Console.Write("info {0}", msg);
101+
}
102+
103+
private void MsgWarning(string msg, IntPtr clientData)
104+
{
105+
Console.Write("warning {0}", msg);
106+
}
107+
108+
private void MsgError(string msg, IntPtr clientData)
109+
{
110+
Console.Write("error {0}", msg);
111+
}
112+
113+
private void FreeUserData(IntPtr data)
114+
{
115+
_image = null;
116+
_offset = 0;
117+
}
118+
119+
private int Read(IntPtr buffer, int bytes, IntPtr userData)
120+
{
121+
if (_offset == _image.Length)
122+
return -1;
123+
124+
var l = Math.Min(bytes, _image.Length - _offset);
125+
Marshal.Copy(_image, _offset, buffer, l);
126+
_offset += l;
127+
return l;
128+
}
129+
130+
private long Skip(long bytes, IntPtr userData)
131+
{
132+
var l = Math.Min((int)bytes, _image.Length - _offset);
133+
_offset += l;
134+
return l;
135+
}
136+
137+
private int Seek(long bytes, IntPtr userData)
138+
{
139+
if (bytes < 0 || bytes >= _image.Length)
140+
return -1;
141+
142+
_offset = (int)bytes;
143+
return 1;
144+
}
145+
}
146+
}

Diff for: testopj/OPJEncode.cs

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
using System;
2+
using System.IO;
3+
using System.Runtime.InteropServices;
4+
using OpenJPEG;
5+
6+
namespace testopj
7+
{
8+
public class OPJEncode
9+
{
10+
private readonly OpenJPEGFunctions.opj_msg_callback _cbInfo;
11+
private readonly OpenJPEGFunctions.opj_msg_callback _cbWarning;
12+
private readonly OpenJPEGFunctions.opj_msg_callback _cbError;
13+
private readonly OpenJPEGFunctions.opj_stream_write_fn _writeFn;
14+
private readonly OpenJPEGFunctions.opj_stream_skip_fn _skipFn;
15+
private readonly OpenJPEGFunctions.opj_stream_seek_fn _seekFn;
16+
17+
private MemoryStream _s;
18+
19+
public OPJEncode()
20+
{
21+
_cbInfo = new OpenJPEGFunctions.opj_msg_callback(MsgInfo);
22+
_cbWarning = new OpenJPEGFunctions.opj_msg_callback(MsgWarning);
23+
_cbError = new OpenJPEGFunctions.opj_msg_callback(MsgError);
24+
_writeFn = new OpenJPEGFunctions.opj_stream_write_fn(Write);
25+
_skipFn = new OpenJPEGFunctions.opj_stream_skip_fn(Skip);
26+
_seekFn = new OpenJPEGFunctions.opj_stream_seek_fn(Seek);
27+
}
28+
29+
/// <summary>
30+
///
31+
/// </summary>
32+
/// <param name="bmp"></param>
33+
/// <param name="r">quality 0-100</param>
34+
/// <returns></returns>
35+
public byte[] Encode(BMPGray16 bmp, float r)
36+
{
37+
_s = new MemoryStream();
38+
39+
var opjImage = IntPtr.Zero;
40+
var opjCodec = IntPtr.Zero;
41+
var opjStream = IntPtr.Zero;
42+
43+
var encoderParametersPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OpenJPEGEncoderParameters)));
44+
var imageCreateParamPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OpenJPEGImageCompParam)));
45+
46+
try
47+
{
48+
var createImageParam = new OpenJPEGImageCompParam
49+
{
50+
w = (uint)bmp.W,
51+
h = (uint)bmp.H,
52+
prec = (uint)bmp.ActualBPP,
53+
dx = 1,
54+
dy = 1
55+
};
56+
57+
Marshal.StructureToPtr(createImageParam, imageCreateParamPtr, false);
58+
opjImage = OpenJPEGFunctions.opj_image_create(1, imageCreateParamPtr, (int)OpenJPEGColorSpace.Gray);
59+
if (opjImage == IntPtr.Zero)
60+
throw new OPJException();
61+
62+
var img = Marshal.PtrToStructure<OpenJPEGImage>(opjImage);
63+
var imgComp = Marshal.PtrToStructure<OpenJPEGImageComp>(img.comps);
64+
65+
img.x1 = createImageParam.w;
66+
img.y1 = createImageParam.h;
67+
Marshal.StructureToPtr(img, opjImage, false);
68+
69+
unsafe
70+
{
71+
var p = (byte*)imgComp.data;
72+
for (var n = 0; n < bmp.Pixels.Length; ++n)
73+
{
74+
var v = bmp.Pixels[n] >> (16 - bmp.ActualBPP);
75+
76+
*p = (byte)(v & 0x00ff);
77+
++p;
78+
79+
*p = (byte)(v >> 8);
80+
p += 3;
81+
}
82+
}
83+
84+
opjCodec = OpenJPEGFunctions.opj_create_compress((int)OpenJPEGCodecFormat.JP2);
85+
OpenJPEGFunctions.opj_set_info_handler(opjCodec, _cbInfo, IntPtr.Zero);
86+
OpenJPEGFunctions.opj_set_warning_handler(opjCodec, _cbWarning, IntPtr.Zero);
87+
OpenJPEGFunctions.opj_set_error_handler(opjCodec, _cbError, IntPtr.Zero);
88+
89+
OpenJPEGFunctions.opj_set_default_encoder_parameters(encoderParametersPtr);
90+
var ep = Marshal.PtrToStructure<OpenJPEGEncoderParameters>(encoderParametersPtr);
91+
ep.cp_disto_alloc = 1;
92+
ep.tcp_numlayers = 1;
93+
ep.tcp_rates[0] = r;
94+
95+
Marshal.StructureToPtr(ep, encoderParametersPtr, false);
96+
if (OpenJPEGFunctions.opj_setup_encoder(opjCodec, encoderParametersPtr, opjImage) != (int)OpenJPEGBool.True)
97+
throw new OPJException();
98+
99+
opjStream = OpenJPEGFunctions.opj_stream_default_create((int)OpenJPEGBool.False);
100+
//opjStream = OpenJPEGFunctions.opj_stream_create_default_file_stream("111.j2k", (int)OpenJPEGBool.False);
101+
if (opjStream == IntPtr.Zero)
102+
throw new OPJException();
103+
104+
OpenJPEGFunctions.opj_stream_set_write_function(opjStream, _writeFn);
105+
OpenJPEGFunctions.opj_stream_set_skip_function(opjStream, _skipFn);
106+
OpenJPEGFunctions.opj_stream_set_seek_function(opjStream, _seekFn);
107+
108+
if (OpenJPEGFunctions.opj_start_compress(opjCodec, opjImage, opjStream) != (int)OpenJPEGBool.True)
109+
throw new OPJException();
110+
111+
if (OpenJPEGFunctions.opj_encode(opjCodec, opjStream) != (int)OpenJPEGBool.True)
112+
throw new OPJException();
113+
114+
if (OpenJPEGFunctions.opj_end_compress(opjCodec, opjStream) != (int)OpenJPEGBool.True)
115+
throw new OPJException();
116+
117+
return _s.ToArray();
118+
}
119+
finally
120+
{
121+
_s = null;
122+
Marshal.FreeHGlobal(imageCreateParamPtr);
123+
Marshal.FreeHGlobal(encoderParametersPtr);
124+
125+
if (opjImage != IntPtr.Zero)
126+
OpenJPEGFunctions.opj_image_destroy(opjImage);
127+
128+
if (opjCodec != IntPtr.Zero)
129+
OpenJPEGFunctions.opj_destroy_codec(opjCodec);
130+
131+
if (opjStream != IntPtr.Zero)
132+
OpenJPEGFunctions.opj_stream_destroy(opjStream);
133+
}
134+
}
135+
136+
private void MsgInfo(string msg, IntPtr clientData)
137+
{
138+
Console.Write("info {0}", msg);
139+
}
140+
141+
private void MsgWarning(string msg, IntPtr clientData)
142+
{
143+
Console.Write("warning {0}", msg);
144+
}
145+
146+
private void MsgError(string msg, IntPtr clientData)
147+
{
148+
Console.Write("error {0}", msg);
149+
}
150+
151+
private int Write(IntPtr buffer, int bytes, IntPtr userData)
152+
{
153+
unsafe
154+
{
155+
var src = new UnmanagedMemoryStream((byte*)buffer.ToPointer(), bytes, bytes, FileAccess.Read);
156+
src.CopyTo(_s);
157+
}
158+
159+
return bytes;
160+
}
161+
162+
private long Skip(long bytes, IntPtr userData)
163+
{
164+
_s.Position += bytes;
165+
return bytes;
166+
}
167+
168+
private int Seek(long bytes, IntPtr userData)
169+
{
170+
_s.Position = bytes;
171+
return 1;
172+
}
173+
}
174+
}

Diff for: testopj/OPJException.cs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
3+
namespace testopj
4+
{
5+
public class OPJException : Exception
6+
{
7+
public OPJException()
8+
{
9+
}
10+
11+
public OPJException(string message)
12+
: base(message)
13+
{
14+
}
15+
16+
public OPJException(string message, Exception innerException)
17+
: base(message, innerException)
18+
{
19+
}
20+
}
21+
}

Diff for: testopj/OpenJPEG/OpenJPEGBool.cs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace OpenJPEG
4+
{
5+
public enum OpenJPEGBool
6+
{
7+
False = 0,
8+
True = 1
9+
}
10+
}

Diff for: testopj/OpenJPEG/OpenJPEGCodecFormat.cs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace OpenJPEG
4+
{
5+
public enum OpenJPEGCodecFormat
6+
{
7+
Unknown = -1,
8+
J2K = 0,
9+
JPT = 1,
10+
JP2 = 2,
11+
JPP = 3,
12+
JPX = 4
13+
}
14+
}

0 commit comments

Comments
 (0)