Krita Source Code Documentation
Loading...
Searching...
No Matches
JP2Converter Class Reference

#include <jp2_converter.h>

+ Inheritance diagram for JP2Converter:

Public Slots

virtual void cancel ()
 

Public Member Functions

void addErrorString (const std::string &str)
 
void addInfoString (const std::string &str)
 
void addWarningString (const std::string &str)
 
KisImportExportErrorCode buildFile (const QString &filename, KisPaintLayerSP layer, const JP2ConvertOptions &options)
 
KisImportExportErrorCode buildImage (const QString &filename)
 
KisImageWSP image ()
 
 JP2Converter (KisDocument *doc)
 
virtual ~JP2Converter ()
 

Private Member Functions

KisImportExportErrorCode decode (const QString &filename)
 
int infile_format (const char *fname)
 

Private Attributes

std::string err
 
KisDocumentm_doc
 
KisImageSP m_image
 
bool m_stop
 
std::string warn
 

Detailed Description

Definition at line 26 of file jp2_converter.h.

Constructor & Destructor Documentation

◆ JP2Converter()

JP2Converter::JP2Converter ( KisDocument * doc)

Definition at line 40 of file jp2_converter.cc.

40 {
41 m_doc = doc;
42 m_stop = false;
43}
KisDocument * m_doc

References m_doc, and m_stop.

◆ ~JP2Converter()

JP2Converter::~JP2Converter ( )
virtual

Definition at line 45 of file jp2_converter.cc.

45 {
46}

Member Function Documentation

◆ addErrorString()

void JP2Converter::addErrorString ( const std::string & str)

Definition at line 411 of file jp2_converter.cc.

411 {
412 if (!err.empty())
413 err += "\n";
414 err += str;
415}
std::string err

References err.

◆ addInfoString()

void JP2Converter::addInfoString ( const std::string & str)

Definition at line 406 of file jp2_converter.cc.

406 {
407 dbgFile
408 << str.c_str();
409}
#define dbgFile
Definition kis_debug.h:56

References dbgFile.

◆ addWarningString()

void JP2Converter::addWarningString ( const std::string & str)

Definition at line 401 of file jp2_converter.cc.

401 {
402 if (!warn.empty())
403 warn += "\n";
404 warn += str;
405}
std::string warn

References warn.

◆ buildFile()

KisImportExportErrorCode JP2Converter::buildFile ( const QString & filename,
KisPaintLayerSP layer,
const JP2ConvertOptions & options )

Definition at line 389 of file jp2_converter.cc.

390 {
391 (void) layer;
392 (void) filename;
393 (void) options;
395}
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)

References ImportExportCodes::Failure, and void().

◆ buildImage()

KisImportExportErrorCode JP2Converter::buildImage ( const QString & filename)

Definition at line 146 of file jp2_converter.cc.

146 {
148 const QByteArray file_str = filename.toUtf8();
149 opj_codec_t *l_codec = 0;
150 opj_dparameters_t parameters;
151 bool hasColorSpaceInfo = false;
152 opj_stream_t *l_stream = NULL;
153 opj_image_t *image = NULL;
154 int pos = 0;
155 KisHLineIteratorSP it = NULL;
156 unsigned int numComponents = 0;
157 unsigned int precision = 0;
158 const KoColorSpace *colorSpace = 0;
159 QVector<int> channelorder;
160 KisPaintLayerSP layer;
161 bool isSigned;
162 int32_t signedCorrection = 0;
163 uint32_t w=0, h=0;
164
165 // decompression parameters
166 opj_set_default_decoder_parameters(&parameters);
167 // Determine the type
168 parameters.decod_format = infile_format(file_str.constData());
169 if (parameters.decod_format == -1) {
170 addErrorString("Not a JPEG 2000 file.");
172 goto beach;
173 }
174
175 // Decode the file
176 /* get a decoder handle */
177 switch (parameters.decod_format) {
178 case J2K_CFMT: {
179 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
180 break;
181 }
182 case JP2_CFMT: {
183 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
184 hasColorSpaceInfo = true;
185 break;
186 }
187 }
188 Q_ASSERT(l_codec);
189
190 opj_codec_set_threads( l_codec,QThread::idealThreadCount() );
191
192 /* setup the decoder decoding parameters using user parameters */
193 opj_setup_decoder(l_codec, &parameters);
194
195 l_stream = opj_stream_create_default_file_stream(file_str.constData(), 1);
196 if (!l_stream) {
197 addErrorString("Failed to create the stream");
199 goto beach;
200 }
201
202 // Setup an event handling
203 opj_set_info_handler(l_codec, info_callback, this);
204 opj_set_error_handler(l_codec, error_callback, this);
205 opj_set_warning_handler(l_codec, warning_callback, this);
206
207 if (!opj_read_header(l_stream, l_codec, &image)) {
208 addErrorString("Failed to read the header");
210 goto beach;
211 }
212
213 /* Get the decoded image */
214 if (!(opj_decode(l_codec, l_stream, image)
215 && opj_end_decompress(l_codec, l_stream))) {
216 addErrorString("Failed to decode image");
218 goto beach;
219 }
220
221 // Look for the colorspace
222 numComponents = image->numcomps;
223 if (image->numcomps == 0) {
224 addErrorString("Image must have at least one component");
226 goto beach;
227 }
228 precision = image->comps[0].prec;
229 for (uint32_t i = 1; i < numComponents; ++i) {
230 if (image->comps[i].prec != precision) {
231 std::ostringstream buffer;
232 buffer << "All components must have the same bit depth "
233 << precision;
234 addErrorString(buffer.str());
236 goto beach;
237 }
238 }
239 isSigned = false;
240 for (uint32_t i = 0; i < numComponents; ++i) {
241 if ((image->comps[i].dx != 1) || (image->comps[i].dy != 1)) {
242 addErrorString("Sub-sampling not supported");
244 goto beach;
245 }
246 isSigned = isSigned || (image->comps[0].sgnd);
247 }
248 if (isSigned)
249 signedCorrection = 1 << (precision - 1);
250
251 dbgFile
252 << "Image has " << numComponents << " numComponents and a bit depth of "
253 << precision << " for color space " << image->color_space;
254 channelorder = QVector<int>(numComponents);
255 if (!hasColorSpaceInfo) {
256 if (numComponents == 3) {
257 image->color_space = OPJ_CLRSPC_SRGB;
258 } else if (numComponents == 1) {
259 image->color_space = OPJ_CLRSPC_GRAY;
260 }
261 }
262 switch (image->color_space) {
263 case OPJ_CLRSPC_UNKNOWN:
264 case OPJ_CLRSPC_UNSPECIFIED:
265 break;
266 case OPJ_CLRSPC_SRGB: {
267 if (precision == 16 || precision == 12) {
268 colorSpace = KoColorSpaceRegistry::instance()->rgb16();
269 } else if (precision == 8) {
270 colorSpace = KoColorSpaceRegistry::instance()->rgb8();
271 }
272 if (numComponents != 3) {
273 std::ostringstream buffer;
274 buffer << "sRGB: number of numComponents " << numComponents
275 << " does not equal 3";
276 addErrorString(buffer.str());
278 goto beach;
279 }
280 channelorder[0] = KoBgrU16Traits::red_pos;
281 channelorder[1] = KoBgrU16Traits::green_pos;
282 channelorder[2] = KoBgrU16Traits::blue_pos;
283 break;
284 }
285 case OPJ_CLRSPC_GRAY: {
286 if (precision == 16 || precision == 12) {
289 } else if (precision == 8) {
292 }
293 if (numComponents != 1) {
294 std::ostringstream buffer;
295 buffer << "Grayscale: number of numComponents " << numComponents
296 << " greater than 1";
297 addErrorString(buffer.str());
299 goto beach;
300 }
301 channelorder[0] = 0;
302 break;
303 }
304 case OPJ_CLRSPC_SYCC:
305 addErrorString("YUV color space not supported");
307 goto beach;
308 break;
309 case OPJ_CLRSPC_EYCC:
310 addErrorString("eYCC color space not supported");
312 goto beach;
313 break;
314 case OPJ_CLRSPC_CMYK:
315 addErrorString("CMYK color space not supported");
317 goto beach;
318 break;
319 default:
320 break;
321 }
322
323 if (!colorSpace) {
324 addErrorString("No color space found for image");
326 goto beach;
327 }
328
329 // Create the image
330 w = (uint32_t)(image->x1 - image->x0);
331 h = (uint32_t)(image->y1 - image->y0);
332 if (m_image == 0) {
333 m_image = new KisImage(m_doc->createUndoStore(), w, h,
334 colorSpace, "built image");
335 }
336
337 // Create the layer
340 m_image->addNode(layer);
341
342 // Set the data
343 it = layer->paintDevice()->createHLineIteratorNG(0, 0, w);
344 for (OPJ_UINT32 v = 0; v < image->y1; ++v) {
345 if (precision == 16 || precision == 12) {
346 do {
347 quint16 *px = reinterpret_cast<quint16*>(it->rawData());
348 for (uint32_t i = 0; i < numComponents; ++i) {
349 px[channelorder[i]] = image->comps[i].data[pos]
350 + signedCorrection;
351 }
352 colorSpace->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
353 ++pos;
354
355 } while (it->nextPixel());
356 } else if (precision == 8) {
357 do {
358 quint8 *px = it->rawData();
359 for (uint32_t i = 0; i < numComponents; ++i) {
360 px[channelorder[i]] = image->comps[i].data[pos]
361 + signedCorrection;
362 }
363 colorSpace->setOpacity(px, OPACITY_OPAQUE_U8, 1);
364 ++pos;
365
366 } while (it->nextPixel());
367 }
368 it->nextRow();
369 }
370
371beach:
372 if (l_stream)
373 opj_stream_destroy(l_stream);
374 if (l_codec)
375 opj_destroy_codec(l_codec);
376 if (image)
377 opj_image_destroy(image);
378 if (!err.empty())
379 m_doc->setErrorMessage(i18n(err.c_str()));
380 if (!warn.empty())
381 m_doc->setWarningMessage(i18n(warn.c_str()));
382 return res;
383}
qreal v
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const quint8 OPACITY_OPAQUE_U8
KisImageSP m_image
int infile_format(const char *fname)
void addErrorString(const std::string &str)
KisImageWSP image()
KisUndoStore * createUndoStore()
void setErrorMessage(const QString &errMsg)
void setWarningMessage(const QString &warningMsg)
QString nextLayerName(const QString &baseName="") const
Definition kis_image.cc:742
KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w)
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
QString id() const
Definition KoID.cpp:63
#define J2K_CFMT
static void warning_callback(const char *msg, void *client_data)
static void error_callback(const char *msg, void *client_data)
#define JP2_CFMT
static void info_callback(const char *msg, void *client_data)
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
KisPaintDeviceSP paintDevice
static const qint32 blue_pos
static const qint32 green_pos
static const qint32 red_pos
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
const KoColorSpace * rgb16(const QString &profileName=QString())

References addErrorString(), KisNodeFacade::addNode(), KoBgrTraits< quint16 >::blue_pos, KoColorSpaceRegistry::colorSpace(), KisPaintDevice::createHLineIteratorNG(), KisDocument::createUndoStore(), dbgFile, err, error_callback(), ImportExportCodes::ErrorWhileReading, ImportExportCodes::Failure, ImportExportCodes::FileFormatIncorrect, ImportExportCodes::FormatColorSpaceUnsupported, ImportExportCodes::FormatFeaturesUnsupported, GrayAColorModelID, KoBgrTraits< quint16 >::green_pos, KoID::id(), image(), infile_format(), info_callback(), KoColorSpaceRegistry::instance(), Integer16BitsColorDepthID, Integer8BitsColorDepthID, J2K_CFMT, JP2_CFMT, m_doc, m_image, KisImage::nextLayerName(), ImportExportCodes::OK, OPACITY_OPAQUE_U8, KisPaintLayer::paintDevice, KoBgrTraits< quint16 >::red_pos, KoColorSpaceRegistry::rgb16(), KoColorSpaceRegistry::rgb8(), KisDocument::setErrorMessage(), KoColorSpace::setOpacity(), KisDocument::setWarningMessage(), v, warn, and warning_callback().

◆ cancel

void JP2Converter::cancel ( )
virtualslot

Definition at line 397 of file jp2_converter.cc.

397 {
398 m_stop = true;
399}

References m_stop.

◆ decode()

KisImportExportErrorCode JP2Converter::decode ( const QString & filename)
private

◆ image()

KisImageWSP JP2Converter::image ( )

Retrieve the constructed image

Definition at line 385 of file jp2_converter.cc.

385 {
386 return m_image;
387}

References m_image.

◆ infile_format()

int JP2Converter::infile_format ( const char * fname)
private

Definition at line 101 of file jp2_converter.cc.

101 {
102 FILE *reader;
103 const char *s, *magic_s;
104 int ext_format, magic_format;
105 unsigned char buf[12];
106 OPJ_SIZE_T l_nb_read;
107
108 reader = fopen(fname, "rb");
109
110 if (reader == NULL) {
111 return -2;
112 }
113
114 memset(buf, 0, 12);
115 l_nb_read = fread(buf, 1, 12, reader);
116 fclose(reader);
117 if (l_nb_read != 12) {
118 return -1;
119 }
120 ext_format = getFileFormat(fname);
121 if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0
122 || memcmp(buf, JP2_MAGIC, 4) == 0) {
123 magic_format = JP2_CFMT;
124 magic_s = ".jp2";
125 } else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
126 magic_format = J2K_CFMT;
127 magic_s = ".j2k, .j2c, .jpc, .jpx, or .jpf";
128 } else {
129 return -1;
130 }
131
132 if (magic_format == ext_format) {
133 return ext_format;
134 }
135
136 if (strlen(fname) >= 4) {
137 s = fname + strlen(fname) - 4;
138 std::ostringstream buffer;
139 buffer << "The extension of this file is incorrect.\n"
140 << "Found " << s << " while it should be " << magic_s << ".";
141 addErrorString(buffer.str());
142 }
143 return magic_format;
144}
static int getFileFormat(const char *filename)
#define JP2_RFC3745_MAGIC
#define J2K_CODESTREAM_MAGIC
#define JP2_MAGIC

References addErrorString(), getFileFormat(), J2K_CFMT, J2K_CODESTREAM_MAGIC, JP2_CFMT, JP2_MAGIC, and JP2_RFC3745_MAGIC.

Member Data Documentation

◆ err

std::string JP2Converter::err
private

Definition at line 52 of file jp2_converter.h.

◆ m_doc

KisDocument* JP2Converter::m_doc
private

Definition at line 50 of file jp2_converter.h.

◆ m_image

KisImageSP JP2Converter::m_image
private

Definition at line 49 of file jp2_converter.h.

◆ m_stop

bool JP2Converter::m_stop
private

Definition at line 51 of file jp2_converter.h.

◆ warn

std::string JP2Converter::warn
private

Definition at line 53 of file jp2_converter.h.


The documentation for this class was generated from the following files: