qrdnicapacitor 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +34 -0
- package/Qrdnicapacitor.podspec +18 -0
- package/README.md +106 -0
- package/android/build.gradle +64 -0
- package/android/src/main/AndroidManifest.xml +16 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/QrCodeScanner.java +84 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/jj2000/ImgStreamWriter.java +483 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/jj2000/J2kStreamDecoder.java +116 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/jj2000/MyFileFormatReader.java +204 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/qrdni.java +130 -0
- package/android/src/main/java/com/cqesolutions/qrdnicapacitor/qrdniPlugin.java +109 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +255 -0
- package/dist/esm/definitions.d.ts +44 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +14 -0
- package/dist/esm/web.js +18 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +32 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +35 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/qrdniPlugin/ScannerViewController.swift +170 -0
- package/ios/Sources/qrdniPlugin/qrdni.swift +111 -0
- package/ios/Sources/qrdniPlugin/qrdniPlugin.swift +105 -0
- package/ios/Tests/qrdniPluginTests/qrdniTests.swift +15 -0
- package/package.json +80 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* CVS identifier:
|
|
3
|
+
*
|
|
4
|
+
* $Id: ImgWriterPPM.java,v 1.16 2002/07/25 15:10:14 grosbois Exp $
|
|
5
|
+
*
|
|
6
|
+
* Class: ImgWriterRawPPM
|
|
7
|
+
*
|
|
8
|
+
* Description: Image writer for unsigned 8 bit data in
|
|
9
|
+
* PPM file format.
|
|
10
|
+
*
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
* COPYRIGHT:
|
|
14
|
+
*
|
|
15
|
+
* This software module was originally developed by Rapha�l Grosbois and
|
|
16
|
+
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
|
|
17
|
+
* Askel�f (Ericsson Radio Systems AB); and Bertrand Berthelot, David
|
|
18
|
+
* Bouchard, F�lix Henry, Gerard Mozelle and Patrice Onno (Canon Research
|
|
19
|
+
* Centre France S.A) in the course of development of the JPEG2000
|
|
20
|
+
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
|
|
21
|
+
* software module is an implementation of a part of the JPEG 2000
|
|
22
|
+
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
|
|
23
|
+
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
|
|
24
|
+
* Partners) agree not to assert against ISO/IEC and users of the JPEG
|
|
25
|
+
* 2000 Standard (Users) any of their rights under the copyright, not
|
|
26
|
+
* including other intellectual property rights, for this software module
|
|
27
|
+
* with respect to the usage by ISO/IEC and Users of this software module
|
|
28
|
+
* or modifications thereof for use in hardware or software products
|
|
29
|
+
* claiming conformance to the JPEG 2000 Standard. Those intending to use
|
|
30
|
+
* this software module in hardware or software products are advised that
|
|
31
|
+
* their use may infringe existing patents. The original developers of
|
|
32
|
+
* this software module, JJ2000 Partners and ISO/IEC assume no liability
|
|
33
|
+
* for use of this software module or modifications thereof. No license
|
|
34
|
+
* or right to this software module is granted for non JPEG 2000 Standard
|
|
35
|
+
* conforming products. JJ2000 Partners have full right to use this
|
|
36
|
+
* software module for his/her own purpose, assign or donate this
|
|
37
|
+
* software module to any third party and to inhibit third parties from
|
|
38
|
+
* using this software module for non JPEG 2000 Standard conforming
|
|
39
|
+
* products. This copyright notice must be included in all copies or
|
|
40
|
+
* derivative works of this software module.
|
|
41
|
+
*
|
|
42
|
+
* Copyright (c) 1999/2000 JJ2000 Partners.
|
|
43
|
+
* */
|
|
44
|
+
package com.cqesolutions.qrdnicapacitor.jj2000;
|
|
45
|
+
|
|
46
|
+
import android.graphics.Bitmap;
|
|
47
|
+
|
|
48
|
+
import java.io.ByteArrayInputStream;
|
|
49
|
+
import java.io.IOException;
|
|
50
|
+
import java.io.InputStream;
|
|
51
|
+
import java.nio.ByteBuffer;
|
|
52
|
+
import java.util.Arrays;
|
|
53
|
+
|
|
54
|
+
import jj2000.j2k.image.BlkImgDataSrc;
|
|
55
|
+
import jj2000.j2k.image.DataBlk;
|
|
56
|
+
import jj2000.j2k.image.DataBlkInt;
|
|
57
|
+
import jj2000.j2k.image.output.ImgWriter;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* This class writes 3 components from an image in 8 bit unsigned data to a
|
|
61
|
+
* binary PPM file.
|
|
62
|
+
*
|
|
63
|
+
* <P>The size of the image that is written is the size of the source
|
|
64
|
+
* image. No component subsampling is allowed in any of the components that
|
|
65
|
+
* are written to the file.
|
|
66
|
+
*
|
|
67
|
+
* <P>Before writing, all coefficients are inversly level-shifted and then
|
|
68
|
+
* "saturated" (they are limited * to the nominal dynamic range).<br>
|
|
69
|
+
*
|
|
70
|
+
* <u>Ex:</u> if the nominal range is 0-255, the following algorithm is
|
|
71
|
+
* applied:<br>
|
|
72
|
+
*
|
|
73
|
+
* <tt>if coeff<0, output=0<br>
|
|
74
|
+
*
|
|
75
|
+
* if coeff>255, output=255<br>
|
|
76
|
+
*
|
|
77
|
+
* else output=coeff</tt>
|
|
78
|
+
*
|
|
79
|
+
* The write() methods of an object of this class may not be called
|
|
80
|
+
* concurrently from different threads.
|
|
81
|
+
*
|
|
82
|
+
* <P>NOTE: This class is not thread safe, for reasons of internal buffering.
|
|
83
|
+
* <P>Modified by D Westland so that it creates a Byte[] rather than a file
|
|
84
|
+
* */
|
|
85
|
+
public class ImgStreamWriter extends ImgWriter {
|
|
86
|
+
|
|
87
|
+
/** Value used to inverse level shift. One for each component */
|
|
88
|
+
private int[] levShift = new int[3];
|
|
89
|
+
|
|
90
|
+
/** Where to write the data */
|
|
91
|
+
private final int CAPACITY = 5000000; //big enough for passport jpegs
|
|
92
|
+
private ByteBuffer buffer = ByteBuffer.allocate(CAPACITY);
|
|
93
|
+
|
|
94
|
+
/** The array of indexes of the components from where to get the data */
|
|
95
|
+
private int cps[] = new int[3];
|
|
96
|
+
|
|
97
|
+
/** The array of the number of fractional bits in the components of the
|
|
98
|
+
source data */
|
|
99
|
+
private int fb[] = new int[3];
|
|
100
|
+
|
|
101
|
+
/** A DataBlk, just used to avoid allocating a new one each time
|
|
102
|
+
it is needed */
|
|
103
|
+
private DataBlkInt db = new DataBlkInt();
|
|
104
|
+
|
|
105
|
+
/** The offset of the raw pixel data in the PPM file */
|
|
106
|
+
private int offset;
|
|
107
|
+
|
|
108
|
+
/** The line buffer. */
|
|
109
|
+
// This makes the class not thrad safe
|
|
110
|
+
// (but it is not the only one making it so)
|
|
111
|
+
private byte buf[];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Creates a new writer to the specified File object, to write data from
|
|
115
|
+
* the specified component.
|
|
116
|
+
*
|
|
117
|
+
* <p>The three components that will be written as R, G and B must be
|
|
118
|
+
* specified through the b1, b2 and b3 arguments.</p>
|
|
119
|
+
*
|
|
120
|
+
*
|
|
121
|
+
* @param imgSrc The source from where to get the image data to write.
|
|
122
|
+
*
|
|
123
|
+
* @param n1 The index of the first component from where to get the data,
|
|
124
|
+
* that will be written as the red channel.
|
|
125
|
+
*
|
|
126
|
+
* @param n2 The index of the second component from where to get the data,
|
|
127
|
+
* that will be written as the green channel.
|
|
128
|
+
*
|
|
129
|
+
* @param n3 The index of the third component from where to get the data,
|
|
130
|
+
* that will be written as the green channel.
|
|
131
|
+
*
|
|
132
|
+
* @see DataBlk
|
|
133
|
+
* */
|
|
134
|
+
public ImgStreamWriter(BlkImgDataSrc imgSrc,
|
|
135
|
+
int n1,int n2,int n3) throws IOException {
|
|
136
|
+
// Check that imgSrc is of the correct type
|
|
137
|
+
// Check that the component index is valid
|
|
138
|
+
if((n1<0) || (n1>=imgSrc.getNumComps()) ||
|
|
139
|
+
(n2<0) || (n2>=imgSrc.getNumComps()) ||
|
|
140
|
+
(n3<0) || (n3>=imgSrc.getNumComps()) ||
|
|
141
|
+
(imgSrc.getNomRangeBits(n1)>8) ||
|
|
142
|
+
(imgSrc.getNomRangeBits(n2)>8) ||
|
|
143
|
+
(imgSrc.getNomRangeBits(n3)>8)) {
|
|
144
|
+
//throw new IllegalArgumentException("Invalid component indexes");
|
|
145
|
+
// In case of Invalid component indexes, lets try with 0,0,0
|
|
146
|
+
if(n1>=imgSrc.getNumComps())
|
|
147
|
+
n1=0;
|
|
148
|
+
if(n2>=imgSrc.getNumComps())
|
|
149
|
+
n2=0;
|
|
150
|
+
if(n3>=imgSrc.getNumComps())
|
|
151
|
+
n3=0;
|
|
152
|
+
}
|
|
153
|
+
// Initialize
|
|
154
|
+
w = imgSrc.getCompImgWidth(n1);
|
|
155
|
+
h = imgSrc.getCompImgHeight(n1);
|
|
156
|
+
// Check that all components have same width and height
|
|
157
|
+
if(w!=imgSrc.getCompImgWidth(n2) ||
|
|
158
|
+
w!=imgSrc.getCompImgWidth(n3) ||
|
|
159
|
+
h!=imgSrc.getCompImgHeight(n2) ||
|
|
160
|
+
h!=imgSrc.getCompImgHeight(n3)) {
|
|
161
|
+
throw new IllegalArgumentException("All components must have the"+
|
|
162
|
+
" same dimensions and no"+
|
|
163
|
+
" subsampling");
|
|
164
|
+
}
|
|
165
|
+
w = imgSrc.getImgWidth();
|
|
166
|
+
h = imgSrc.getImgHeight();
|
|
167
|
+
|
|
168
|
+
// Continue initialization
|
|
169
|
+
buffer.clear();
|
|
170
|
+
|
|
171
|
+
src = imgSrc;
|
|
172
|
+
cps[0] = n1;
|
|
173
|
+
cps[1] = n2;
|
|
174
|
+
cps[2] = n3;
|
|
175
|
+
fb[0] = imgSrc.getFixedPoint(n1);
|
|
176
|
+
fb[1] = imgSrc.getFixedPoint(n2);
|
|
177
|
+
fb[2] = imgSrc.getFixedPoint(n3);
|
|
178
|
+
|
|
179
|
+
levShift[0] = 1<< (imgSrc.getNomRangeBits(n1)-1);
|
|
180
|
+
levShift[1] = 1<< (imgSrc.getNomRangeBits(n2)-1);
|
|
181
|
+
levShift[2] = 1<< (imgSrc.getNomRangeBits(n3)-1);
|
|
182
|
+
|
|
183
|
+
writeHeaderInfo();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Closes the underlying file or network connection to where the data is
|
|
189
|
+
* written. Any call to other methods of the class become illegal after a
|
|
190
|
+
* call to this one.
|
|
191
|
+
*
|
|
192
|
+
* @exception IOException If an I/O error occurs.
|
|
193
|
+
* */
|
|
194
|
+
public void close() throws IOException {
|
|
195
|
+
src = null;
|
|
196
|
+
db = null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Writes all buffered data to the file or resource.
|
|
201
|
+
*
|
|
202
|
+
* @exception IOException If an I/O error occurs.
|
|
203
|
+
* */
|
|
204
|
+
public void flush() throws IOException {
|
|
205
|
+
// No flush needed here since we are using a RandomAccessFile Get rid
|
|
206
|
+
// of line buffer (is this a good choice?)
|
|
207
|
+
buf = null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Writes the data of the specified area to the file, coordinates are
|
|
212
|
+
* relative to the current tile of the source. Before writing, the
|
|
213
|
+
* coefficients are limited to the nominal range.
|
|
214
|
+
*
|
|
215
|
+
* <p>This method may not be called concurrently from different
|
|
216
|
+
* threads.</p>
|
|
217
|
+
*
|
|
218
|
+
* <p>If the data returned from the BlkImgDataSrc source is progressive,
|
|
219
|
+
* then it is requested over and over until it is not progressive
|
|
220
|
+
* anymore.</p>
|
|
221
|
+
*
|
|
222
|
+
* @param ulx The horizontal coordinate of the upper-left corner of the
|
|
223
|
+
* area to write, relative to the current tile.
|
|
224
|
+
*
|
|
225
|
+
* @param uly The vertical coordinate of the upper-left corner of the area
|
|
226
|
+
* to write, relative to the current tile.
|
|
227
|
+
*
|
|
228
|
+
* @param w The width of the area to write.
|
|
229
|
+
*
|
|
230
|
+
* @param h The height of the area to write.
|
|
231
|
+
*
|
|
232
|
+
* @exception IOException If an I/O error occurs.
|
|
233
|
+
* */
|
|
234
|
+
public void write(int ulx, int uly, int w, int h) throws IOException {
|
|
235
|
+
int k,j,i,c;
|
|
236
|
+
// In local variables for faster access
|
|
237
|
+
int fracbits;
|
|
238
|
+
// variables used during coeff saturation
|
|
239
|
+
int shift,tmp,maxVal;
|
|
240
|
+
int tOffx, tOffy; // Active tile offset in the X and Y direction
|
|
241
|
+
|
|
242
|
+
// Active tiles in all components have same offset since they are at
|
|
243
|
+
// same resolution (PPM does not support anything else)
|
|
244
|
+
tOffx = src.getCompULX(cps[0]) -
|
|
245
|
+
(int)Math.ceil(src.getImgULX()/(double)src.getCompSubsX(cps[0]));
|
|
246
|
+
tOffy = src.getCompULY(cps[0]) -
|
|
247
|
+
(int)Math.ceil(src.getImgULY()/(double)src.getCompSubsY(cps[0]));
|
|
248
|
+
|
|
249
|
+
// Check the array size
|
|
250
|
+
if(db.data!=null && db.data.length<w) {
|
|
251
|
+
// A new one will be allocated by getInternCompData()
|
|
252
|
+
db.data = null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Check the line buffer
|
|
256
|
+
if(buf==null || buf.length<3*w) {
|
|
257
|
+
buf = new byte[3*w];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Write the data to the file
|
|
261
|
+
// Write line by line
|
|
262
|
+
for(i=0; i<h; i++) {
|
|
263
|
+
// Write into buffer first loop over the three components and
|
|
264
|
+
// write for each
|
|
265
|
+
for(c=0; c<3; c++) {
|
|
266
|
+
maxVal= (1<<src.getNomRangeBits(cps[c]))-1;
|
|
267
|
+
shift = levShift[c];
|
|
268
|
+
|
|
269
|
+
// Initialize db
|
|
270
|
+
db.ulx = ulx;
|
|
271
|
+
db.uly = uly+i;
|
|
272
|
+
db.w = w;
|
|
273
|
+
db.h = 1;
|
|
274
|
+
|
|
275
|
+
// Request the data and make sure it is not progressive
|
|
276
|
+
do {
|
|
277
|
+
db = (DataBlkInt)src.getInternCompData(db,cps[c]);
|
|
278
|
+
} while (db.progressive);
|
|
279
|
+
// Get the fracbits value
|
|
280
|
+
fracbits = fb[c];
|
|
281
|
+
// Write all bytes in the line
|
|
282
|
+
if(fracbits==0) {
|
|
283
|
+
for(k=db.offset+w-1, j=3*w-1+c-2; j>=0; k--) {
|
|
284
|
+
tmp = db.data[k]+shift;
|
|
285
|
+
buf[j] = (byte)((tmp<0)? 0 : ((tmp>maxVal)?
|
|
286
|
+
maxVal : tmp));
|
|
287
|
+
j -= 3;
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
for(k=db.offset+w-1, j=3*w-1+c-2; j>=0; k--) {
|
|
291
|
+
tmp = (db.data[k]>>>fracbits)+shift;
|
|
292
|
+
buf[j] = (byte)((tmp<0)? 0 : ((tmp>maxVal)?
|
|
293
|
+
maxVal : tmp));
|
|
294
|
+
j -= 3;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// Write buffer into file
|
|
299
|
+
int psn = offset+3*(this.w*(uly+tOffy+i)+ulx+tOffx);
|
|
300
|
+
buffer.position(psn);
|
|
301
|
+
buffer.put(buf, 0, 3*w);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Writes the source's current tile to the output. The requests of data
|
|
307
|
+
* issued to the source BlkImgDataSrc object are done by strips, in order
|
|
308
|
+
* to reduce memory usage.
|
|
309
|
+
*
|
|
310
|
+
* <P>If the data returned from the BlkImgDataSrc source is progressive,
|
|
311
|
+
* then it is requested over and over until it is not progressive any
|
|
312
|
+
* more.
|
|
313
|
+
*
|
|
314
|
+
* @exception IOException If an I/O error occurs.
|
|
315
|
+
* */
|
|
316
|
+
public void write() throws IOException {
|
|
317
|
+
int i;
|
|
318
|
+
int tIdx = src.getTileIdx();
|
|
319
|
+
int tw = src.getTileCompWidth(tIdx,0); // Tile width
|
|
320
|
+
int th = src.getTileCompHeight(tIdx, 0); // Tile height
|
|
321
|
+
// Write in strips
|
|
322
|
+
for(i=0; i<th ; i+=DEF_STRIP_HEIGHT) {
|
|
323
|
+
write(0,i,tw,((th-i)<DEF_STRIP_HEIGHT) ? th-i : DEF_STRIP_HEIGHT);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Writes the header info of the PPM file :
|
|
329
|
+
*
|
|
330
|
+
* P6<br>
|
|
331
|
+
*
|
|
332
|
+
* width height<br>
|
|
333
|
+
*
|
|
334
|
+
* 255<br>
|
|
335
|
+
*
|
|
336
|
+
* @exception IOException If there is an I/O Error
|
|
337
|
+
* */
|
|
338
|
+
private void writeHeaderInfo() throws IOException {
|
|
339
|
+
byte[] byteVals;
|
|
340
|
+
int i;
|
|
341
|
+
String val;
|
|
342
|
+
|
|
343
|
+
// write 'P6' to file
|
|
344
|
+
buffer.position(0);
|
|
345
|
+
buffer.put((byte) 80);
|
|
346
|
+
buffer.put((byte) 54);
|
|
347
|
+
buffer.put((byte) 10);
|
|
348
|
+
offset=3;
|
|
349
|
+
// Write width in ASCII
|
|
350
|
+
val=String.valueOf(w);
|
|
351
|
+
byteVals=val.getBytes();
|
|
352
|
+
for(i=0;i<byteVals.length;i++) {
|
|
353
|
+
buffer.put(byteVals[i]);
|
|
354
|
+
offset++;
|
|
355
|
+
}
|
|
356
|
+
buffer.put((byte)32);
|
|
357
|
+
offset++;
|
|
358
|
+
// Write height in ASCII
|
|
359
|
+
val=String.valueOf(h);
|
|
360
|
+
byteVals=val.getBytes();
|
|
361
|
+
for(i=0;i<byteVals.length;i++) {
|
|
362
|
+
buffer.put(byteVals[i]);
|
|
363
|
+
offset++;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
buffer.put((byte)10);
|
|
367
|
+
buffer.put((byte)50);
|
|
368
|
+
buffer.put((byte)53);
|
|
369
|
+
buffer.put((byte)53);
|
|
370
|
+
buffer.put((byte)10);
|
|
371
|
+
offset+=5;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
public ByteArrayInputStream getByteArrayInputStream() {
|
|
375
|
+
//buffer.flip();
|
|
376
|
+
byte[] contents = Arrays.copyOf( buffer.array(), buffer.position());
|
|
377
|
+
return new ByteArrayInputStream(contents);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
public Bitmap getImage() throws IOException {
|
|
381
|
+
writeAll();
|
|
382
|
+
byte[] contents = Arrays.copyOf( buffer.array(), buffer.position());
|
|
383
|
+
PPMConverter ppmc = new PPMConverter(new ByteArrayInputStream(contents));
|
|
384
|
+
return ppmc.createBufferedImage();
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Returns a string of information about the object, more than 1 line
|
|
388
|
+
* long. The information string includes information from the underlying
|
|
389
|
+
* RandomAccessFile (its toString() method is called in turn).
|
|
390
|
+
*
|
|
391
|
+
* @return A string of information about the object.
|
|
392
|
+
* */
|
|
393
|
+
public String toString() {
|
|
394
|
+
return "ImgWriterPPM: WxH = " + w + "x" + h + ", Components = " +
|
|
395
|
+
cps[0]+","+cps[1]+","+cps[2]+ "\nUnderlying RandomAccessFile:\n";
|
|
396
|
+
}
|
|
397
|
+
private class PPMConverter {
|
|
398
|
+
/**
|
|
399
|
+
* Converts a .ppm file into an android bitmap
|
|
400
|
+
*
|
|
401
|
+
* @author duncan
|
|
402
|
+
*
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
InputStream is;
|
|
406
|
+
|
|
407
|
+
private PPMConverter(InputStream is) {
|
|
408
|
+
this.is = is;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
//public BufferedImage createBufferedImage() throws IOException {
|
|
412
|
+
public Bitmap createBufferedImage() throws IOException {
|
|
413
|
+
|
|
414
|
+
if (!readUntilWhiteSpace(is).equals("P6")) throw new IOException();
|
|
415
|
+
int width = Integer.parseInt(readUntilWhiteSpace(is));
|
|
416
|
+
int height = Integer.parseInt(readUntilWhiteSpace(is));
|
|
417
|
+
int depth = Integer.parseInt(readUntilWhiteSpace(is));
|
|
418
|
+
if (depth!=0xFF) throw new IOException("This decoder only accepts 8-bit image depth");
|
|
419
|
+
//BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
|
|
420
|
+
Bitmap img = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888);
|
|
421
|
+
//WritableRaster raster = img.getRaster();
|
|
422
|
+
int[] pixel = new int[3];
|
|
423
|
+
// Read in the pixels
|
|
424
|
+
for (int y = 0; y < height; y++) {
|
|
425
|
+
for (int x = 0; x < width; x++) {
|
|
426
|
+
int red = is.read();
|
|
427
|
+
int green = is.read();
|
|
428
|
+
int blue = is.read();
|
|
429
|
+
if (red>255 || red<0) {
|
|
430
|
+
//Log.e(DEBUG,"Red out of range");
|
|
431
|
+
throw new IOException();
|
|
432
|
+
}
|
|
433
|
+
if (green>255 || green<0) {
|
|
434
|
+
//Log.e(DEBUG,"Green out of range");
|
|
435
|
+
throw new IOException();
|
|
436
|
+
}
|
|
437
|
+
if (blue>255 || blue<0) {
|
|
438
|
+
//Log.e(DEBUG,"Blue out of range");
|
|
439
|
+
throw new IOException();
|
|
440
|
+
}
|
|
441
|
+
pixel[0]=red;
|
|
442
|
+
pixel[1]=green;
|
|
443
|
+
pixel[2]=blue;
|
|
444
|
+
//raster.setPixel(x, y, pixel);
|
|
445
|
+
img.setPixel(x, y, getIntFromColor(pixel[0],pixel[1],pixel[2]));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return img;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
public int getIntFromColor(int Red, int Green, int Blue){
|
|
452
|
+
Red = (Red << 16) & 0x00FF0000; //Shift red 16-bits and mask out other stuff
|
|
453
|
+
Green = (Green << 8) & 0x0000FF00; //Shift Green 8-bits and mask out other stuff
|
|
454
|
+
Blue = Blue & 0x000000FF; //Mask out anything not blue.
|
|
455
|
+
|
|
456
|
+
return 0xFF000000 | Red | Green | Blue; //0xFF000000 for 100% Alpha. Bitwise OR everything together.
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Read characters until whitespace is encountered, then returns a string
|
|
462
|
+
* DOES NOT CHECK FOR EOF
|
|
463
|
+
* @return
|
|
464
|
+
* @throws IOException
|
|
465
|
+
*/
|
|
466
|
+
public String readUntilWhiteSpace(InputStream is) throws IOException {
|
|
467
|
+
String data="";
|
|
468
|
+
int b;
|
|
469
|
+
char next = (char) is.read();
|
|
470
|
+
//skip any whitespace
|
|
471
|
+
while(next =='\n' || next ==' ' || next=='\t') {
|
|
472
|
+
next = (char) is.read();
|
|
473
|
+
}
|
|
474
|
+
while(next !='\n' && next !=' ' && next!='\t') {
|
|
475
|
+
data += next;
|
|
476
|
+
b = is.read();
|
|
477
|
+
if (b==-1) throw new IOException("Unexpected EOF while reading header");
|
|
478
|
+
next = (char)b;
|
|
479
|
+
}
|
|
480
|
+
return data;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package com.cqesolutions.qrdnicapacitor.jj2000;
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap;
|
|
4
|
+
|
|
5
|
+
import java.io.EOFException;
|
|
6
|
+
import java.io.IOException;
|
|
7
|
+
import java.io.InputStream;
|
|
8
|
+
|
|
9
|
+
import colorspace.ColorSpace;
|
|
10
|
+
import colorspace.ColorSpaceException;
|
|
11
|
+
import icc.ICCProfileException;
|
|
12
|
+
import jj2000.j2k.codestream.HeaderInfo;
|
|
13
|
+
import jj2000.j2k.codestream.reader.BitstreamReaderAgent;
|
|
14
|
+
import jj2000.j2k.codestream.reader.HeaderDecoder;
|
|
15
|
+
import jj2000.j2k.decoder.Decoder;
|
|
16
|
+
import jj2000.j2k.decoder.DecoderSpecs;
|
|
17
|
+
import jj2000.j2k.entropy.decoder.EntropyDecoder;
|
|
18
|
+
import jj2000.j2k.image.BlkImgDataSrc;
|
|
19
|
+
import jj2000.j2k.image.ImgDataConverter;
|
|
20
|
+
import jj2000.j2k.image.invcomptransf.InvCompTransf;
|
|
21
|
+
import jj2000.j2k.quantization.dequantizer.Dequantizer;
|
|
22
|
+
import jj2000.j2k.roi.ROIDeScaler;
|
|
23
|
+
import jj2000.j2k.util.ISRandomAccessIO;
|
|
24
|
+
import jj2000.j2k.util.ParameterList;
|
|
25
|
+
import jj2000.j2k.wavelet.synthesis.InverseWT;
|
|
26
|
+
|
|
27
|
+
public class J2kStreamDecoder {
|
|
28
|
+
|
|
29
|
+
public J2kStreamDecoder() {
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public Bitmap decode(InputStream is) throws EOFException, IOException,
|
|
33
|
+
ColorSpaceException, ICCProfileException {
|
|
34
|
+
ISRandomAccessIO in = new ISRandomAccessIO(is);
|
|
35
|
+
ParameterList defpl = new ParameterList();
|
|
36
|
+
String[][] param = Decoder.getAllParameters();
|
|
37
|
+
|
|
38
|
+
for (int i = param.length - 1; i >= 0; i--) {
|
|
39
|
+
if (param[i][3] != null)
|
|
40
|
+
defpl.put(param[i][0], param[i][3]);
|
|
41
|
+
}
|
|
42
|
+
// Create parameter list using defaults
|
|
43
|
+
ParameterList pl = new ParameterList(defpl);
|
|
44
|
+
|
|
45
|
+
// **** File Format ****
|
|
46
|
+
// If the codestream is wrapped in the jp2 fileformat, Read the
|
|
47
|
+
// file format wrapper
|
|
48
|
+
MyFileFormatReader ff = new MyFileFormatReader(in);
|
|
49
|
+
ff.readFileFormat();
|
|
50
|
+
if (ff.JP2FFUsed) {
|
|
51
|
+
in.seek(ff.getFirstCodeStreamPos());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// **** header decoder ****
|
|
55
|
+
HeaderInfo hi = new HeaderInfo();
|
|
56
|
+
HeaderDecoder hd = null;
|
|
57
|
+
DecoderSpecs decSpec = null;
|
|
58
|
+
hd = new HeaderDecoder(in, pl, hi);
|
|
59
|
+
decSpec = hd.getDecoderSpecs();
|
|
60
|
+
// Get demixed bitdepths
|
|
61
|
+
int nCompCod = hd.getNumComps();
|
|
62
|
+
int[] depth = new int[nCompCod];
|
|
63
|
+
for (int i = 0; i < nCompCod; i++) {
|
|
64
|
+
depth[i] = hd.getOriginalBitDepth(i);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// **** Bit stream reader ****
|
|
68
|
+
BitstreamReaderAgent breader = BitstreamReaderAgent.createInstance(in,
|
|
69
|
+
hd, pl, decSpec, pl.getBooleanParameter("cdstr_info"), hi);
|
|
70
|
+
|
|
71
|
+
// **** Entropy decoder ****
|
|
72
|
+
EntropyDecoder entdec = hd.createEntropyDecoder(breader, pl);
|
|
73
|
+
|
|
74
|
+
// **** ROI de-scaler ****
|
|
75
|
+
ROIDeScaler roids = hd.createROIDeScaler(entdec, pl, decSpec);
|
|
76
|
+
|
|
77
|
+
// **** Dequantizer ****
|
|
78
|
+
Dequantizer deq = hd.createDequantizer(roids, depth, decSpec);
|
|
79
|
+
|
|
80
|
+
// full page inverse wavelet transform
|
|
81
|
+
InverseWT invWT = InverseWT.createInstance(deq, decSpec);
|
|
82
|
+
int res = breader.getImgRes();
|
|
83
|
+
invWT.setImgResLevel(res);
|
|
84
|
+
|
|
85
|
+
// **** Data converter **** (after inverse transform module)
|
|
86
|
+
ImgDataConverter converter = new ImgDataConverter(invWT, 0);
|
|
87
|
+
|
|
88
|
+
// **** Inverse component transformation ****
|
|
89
|
+
InvCompTransf ictransf = new InvCompTransf(converter, decSpec, depth,
|
|
90
|
+
pl);
|
|
91
|
+
|
|
92
|
+
// **** Color space mapping ****
|
|
93
|
+
ColorSpace csMap;
|
|
94
|
+
BlkImgDataSrc color = null;
|
|
95
|
+
BlkImgDataSrc palettized;
|
|
96
|
+
BlkImgDataSrc resampled;
|
|
97
|
+
BlkImgDataSrc channels;
|
|
98
|
+
if (ff.JP2FFUsed && pl.getParameter("nocolorspace").equals("off")) {
|
|
99
|
+
csMap = new ColorSpace(in, hd, pl);
|
|
100
|
+
channels = hd.createChannelDefinitionMapper(ictransf, csMap);
|
|
101
|
+
resampled = hd.createResampler(channels, csMap);
|
|
102
|
+
palettized = hd.createPalettizedColorSpaceMapper(resampled, csMap);
|
|
103
|
+
color = hd.createColorSpaceMapper(palettized, csMap);
|
|
104
|
+
} else { // Skip colorspace mapping
|
|
105
|
+
color = ictransf;
|
|
106
|
+
}
|
|
107
|
+
// This is the last image in the decoding chain
|
|
108
|
+
BlkImgDataSrc decodedImage = color;
|
|
109
|
+
if (color == null) {
|
|
110
|
+
decodedImage = ictransf;
|
|
111
|
+
}
|
|
112
|
+
// write out the image
|
|
113
|
+
ImgStreamWriter imwriter = new ImgStreamWriter(decodedImage, 0, 1, 2);
|
|
114
|
+
return imwriter.getImage();
|
|
115
|
+
}
|
|
116
|
+
}
|