void ScImgDataLoader_JPEG::loadEmbeddedProfile(const QString& fn, int /*page*/) { m_embeddedProfile.resize(0); m_profileComponents = 0; if (!QFile::exists(fn)) return; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; infile = NULL; if (setjmp (jerr.setjmp_buffer)) { jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); return; } jpeg_create_decompress (&cinfo); if ((infile = fopen (fn.toLocal8Bit(), "rb")) == NULL) return; jpeg_stdio_src(&cinfo, infile); jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF); jpeg_read_header(&cinfo, true); //jpeg_start_decompress(&cinfo); unsigned int EmbedLen = 0; unsigned char* EmbedBuffer; if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen)) { cmsHPROFILE prof = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen); if (prof) { if (static_cast<int>(cmsGetColorSpace(prof)) == icSigRgbData) m_profileComponents = 3; if (static_cast<int>(cmsGetColorSpace(prof)) == icSigCmykData) m_profileComponents = 4; if (static_cast<int>(cmsGetColorSpace(prof)) == icSigGrayData) m_profileComponents = 1; m_embeddedProfile = QByteArray((const char*) EmbedBuffer, EmbedLen); } cmsCloseProfile(prof); free(EmbedBuffer); } //(void) jpeg_finish_decompress(&cinfo); fclose (infile); jpeg_destroy_decompress (&cinfo); }
void ScImgDataLoader_JPEG::loadEmbeddedProfile(const QString& fn, int /*page*/) { m_embeddedProfile.resize(0); m_profileComponents = 0; if (!QFile::exists(fn)) return; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; infile = NULL; if (setjmp (jerr.setjmp_buffer)) { jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); return; } jpeg_create_decompress (&cinfo); if ((infile = fopen (fn.toLocal8Bit(), "rb")) == NULL) return; jpeg_stdio_src(&cinfo, infile); jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF); jpeg_read_header(&cinfo, true); unsigned int EmbedLen = 0; unsigned char* EmbedBuffer; if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen)) { QByteArray profArray = QByteArray((const char*) EmbedBuffer, EmbedLen); ScColorProfile prof = ScColorMgmtEngine::openProfileFromMem(profArray); if (prof) { if (prof.colorSpace() == ColorSpace_Rgb) m_profileComponents = 3; if (prof.colorSpace() == ColorSpace_Cmyk) m_profileComponents = 4; if (prof.colorSpace() == ColorSpace_Gray) m_profileComponents = 1; m_embeddedProfile = profArray; } free(EmbedBuffer); } fclose (infile); jpeg_destroy_decompress (&cinfo); }
bool ScImgDataLoader_JPEG::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail) { bool isCMYK = false; bool fromPS = false; float xres = 72.0, yres = 72.0; if (!QFile::exists(fn)) return false; ExifData ExifInf; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; infile = NULL; initialize(); m_imageInfoRecord.type = ImageTypeJPG; m_imageInfoRecord.exifInfo.thumbnail = QImage(); if (setjmp (jerr.setjmp_buffer)) { jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); return false; } jpeg_create_decompress (&cinfo); if ((infile = fopen (fn.toLocal8Bit(), "rb")) == NULL) return false; jpeg_stdio_src(&cinfo, infile); jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF); jpeg_save_markers(&cinfo, PHOTOSHOP_MARKER, 0xFFFF); jpeg_read_header(&cinfo, true); jpeg_start_decompress(&cinfo); bool exi = ExifInf.scan(fn); if ((exi) && (ExifInf.exifDataValid)) { if (cinfo.output_components == 4) m_imageInfoRecord.colorspace = ColorSpaceCMYK; else if (cinfo.output_components == 3) m_imageInfoRecord.colorspace = ColorSpaceRGB; else if (cinfo.output_components == 1) m_imageInfoRecord.colorspace = ColorSpaceGray; if ((!ExifInf.Thumbnail.isNull()) && thumbnail) { m_image = ExifInf.getThumbnail(); m_imageInfoRecord.exifInfo.thumbnail = ExifInf.getThumbnail(); if (cinfo.output_components == 4) { QRgb *s; unsigned char cc, cm, cy, ck; for( int yit=0; yit < m_image.height(); ++yit ) { s = (QRgb*)(m_image.scanLine( yit )); for(int xit=0; xit < m_image.width(); ++xit ) { cc = 255 - qRed(*s); cm = 255 - qGreen(*s); cy = 255 - qBlue(*s); ck = qMin(qMin(cc, cm), cy); *s = qRgba(cc-ck,cm-ck,cy-ck,ck); s++; } } } } else m_imageInfoRecord.exifInfo.thumbnail = QImage(); m_imageInfoRecord.exifInfo.cameraName = ExifInf.getCameraModel(); m_imageInfoRecord.exifInfo.cameraVendor = ExifInf.getCameraMake(); m_imageInfoRecord.exifInfo.comment = ExifInf.getComment(); m_imageInfoRecord.exifInfo.width = ExifInf.getWidth(); m_imageInfoRecord.exifInfo.height = ExifInf.getHeight(); m_imageInfoRecord.exifInfo.userComment = ExifInf.getUserComment(); m_imageInfoRecord.exifInfo.dateTime = ExifInf.getDateTime(); m_imageInfoRecord.exifInfo.ApertureFNumber = ExifInf.getApertureFNumber(); m_imageInfoRecord.exifInfo.ExposureTime = ExifInf.getExposureTime(); m_imageInfoRecord.exifInfo.ISOequivalent = ExifInf.getISOequivalent(); m_imageInfoRecord.exifDataValid = true; if (cinfo.density_unit == 0) { xres = 72; yres = 72; } else if ( cinfo.density_unit == 1 ) { xres = cinfo.X_density; yres = cinfo.Y_density; } else if ( cinfo.density_unit == 2 ) { xres = cinfo.X_density * 2.54; yres = cinfo.Y_density * 2.54; } if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 ) { xres = yres = 72.0; QFileInfo qfi(fn); m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName()); m_msgType = warningMsg; } m_imageInfoRecord.xres = qRound(xres); m_imageInfoRecord.yres = qRound(yres); m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo); if ((!ExifInf.Thumbnail.isNull()) && thumbnail) { jpeg_destroy_decompress(&cinfo); fclose(infile); return true; } } else m_imageInfoRecord.exifDataValid = false; m_imageInfoRecord.exifInfo.thumbnail = QImage(); unsigned int EmbedLen = 0; unsigned char* EmbedBuffer; if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen)) { QByteArray profArray = QByteArray((const char*) EmbedBuffer, EmbedLen); ScColorProfile prof = ScColorMgmtEngine::openProfileFromMem(profArray); m_embeddedProfile = profArray; m_imageInfoRecord.profileName = prof.productDescription(); m_imageInfoRecord.isEmbedded = true; free(EmbedBuffer); } else { m_imageInfoRecord.isEmbedded = false; m_imageInfoRecord.profileName = ""; } unsigned int PhotoshopLen = 0; unsigned char * PhotoshopBuffer; if (cinfo.density_unit == 0) { xres = 72; yres = 72; m_image.setDotsPerMeterX(2834); m_image.setDotsPerMeterY(2834); } else if ( cinfo.density_unit == 1 ) { xres = cinfo.X_density; yres = cinfo.Y_density; m_image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) ); m_image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) ); } else if ( cinfo.density_unit == 2 ) { xres = cinfo.X_density * 2.54; yres = cinfo.Y_density * 2.54; m_image.setDotsPerMeterX( int(100. * cinfo.X_density) ); m_image.setDotsPerMeterY( int(100. * cinfo.Y_density) ); } if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 ) { xres = yres = 72.0; m_image.setDotsPerMeterX(2834); m_image.setDotsPerMeterY(2834); QFileInfo qfi(fn); m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName()); m_msgType = warningMsg; } m_imageInfoRecord.xres = qRound(xres); m_imageInfoRecord.yres = qRound(yres); if (cinfo.output_components == 4) { isCMYK = true; m_imageInfoRecord.colorspace = ColorSpaceCMYK; } else if (cinfo.output_components == 3) m_imageInfoRecord.colorspace = ColorSpaceRGB; else if (cinfo.output_components == 1) m_imageInfoRecord.colorspace = ColorSpaceGray; m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo); if (read_jpeg_marker(PHOTOSHOP_MARKER,&cinfo, &PhotoshopBuffer, &PhotoshopLen) ) { if (PhotoshopLen != 0) { bool savEx = m_imageInfoRecord.exifDataValid; QByteArray arrayPhot(PhotoshopLen, ' '); arrayPhot = QByteArray::fromRawData((const char*)PhotoshopBuffer,PhotoshopLen); QDataStream strPhot(&arrayPhot,QIODevice::ReadOnly); strPhot.setByteOrder( QDataStream::BigEndian ); PSDHeader fakeHeader; fakeHeader.width = cinfo.output_width; fakeHeader.height = cinfo.output_height; if (cinfo.output_components == 4) m_imageInfoRecord.colorspace = ColorSpaceCMYK; else if (cinfo.output_components == 3) m_imageInfoRecord.colorspace = ColorSpaceRGB; else if (cinfo.output_components == 1) m_imageInfoRecord.colorspace = ColorSpaceGray; m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo); parseRessourceData(strPhot, fakeHeader, PhotoshopLen); // Photoshop resolution is more accurate than jpeg header resolution xres = m_imageInfoRecord.xres; yres = m_imageInfoRecord.yres; m_image.setDotsPerMeterX( int(100. * m_imageInfoRecord.xres / 2.54) ); m_image.setDotsPerMeterY( int(100. * m_imageInfoRecord.yres / 2.54) ); if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 ) { xres = yres = 72.0; m_imageInfoRecord.xres = qRound(xres); m_imageInfoRecord.yres = qRound(yres); m_image.setDotsPerMeterX(2834); m_image.setDotsPerMeterY(2834); QFileInfo qfi(fn); m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName()); m_msgType = warningMsg; } if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail) { m_image = QImage(m_imageInfoRecord.exifInfo.width, m_imageInfoRecord.exifInfo.height, QImage::Format_ARGB32 ); m_imageInfoRecord.exifInfo.width = cinfo.output_width; m_imageInfoRecord.exifInfo.height = cinfo.output_height; if (cinfo.output_components == 4) { QRgb *d; QRgb *s; unsigned char cc, cm, cy, ck; for( int yit=0; yit < m_image.height(); ++yit ) { d = (QRgb*)(m_image.scanLine( yit )); s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit )); for(int xit=0; xit < m_image.width(); ++xit ) { cc = 255 - qRed(*s); cm = 255 - qGreen(*s); cy = 255 - qBlue(*s); ck = qMin(qMin(cc, cm), cy); *d = qRgba(cc-ck,cm-ck,cy-ck,ck); s++; d++; } } } else m_image = m_imageInfoRecord.exifInfo.thumbnail.copy(); } m_imageInfoRecord.valid = (m_imageInfoRecord.PDSpathData.size())>0?true:false; // The only interest is vectormask arrayPhot.clear(); free( PhotoshopBuffer ); if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail) { jpeg_destroy_decompress(&cinfo); fclose(infile); return true; } m_imageInfoRecord.exifInfo.thumbnail = QImage(); m_imageInfoRecord.exifDataValid = savEx; fromPS = true; } } if ( cinfo.output_components == 3 || cinfo.output_components == 4) m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 ); else if ( cinfo.output_components == 1 ) { m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8 ); m_image.setNumColors(256); for (int i=0; i<256; i++) m_image.setColor(i, qRgb(i,i,i)); } if (!m_image.isNull()) { uchar* data = m_image.bits(); int bpl = m_image.bytesPerLine(); while (cinfo.output_scanline < cinfo.output_height) { uchar *d = data + cinfo.output_scanline * bpl; (void) jpeg_read_scanlines(&cinfo, &d, 1); } if ( cinfo.output_components == 3 ) { uchar *in; QRgb *out; for (uint j=0; j<cinfo.output_height; j++) { in = m_image.scanLine(j) + cinfo.output_width * 3; out = (QRgb*) m_image.scanLine(j); for (uint i=cinfo.output_width; i--; ) { in -= 3; out[i] = qRgb(in[0], in[1], in[2]); } } } if ( cinfo.output_components == 4 ) { int method = 0; if (cinfo.jpeg_color_space == JCS_YCCK) method = 1; else if (fromPS) { if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker) && (cinfo.Adobe_transform == 0)) method = 2; } else if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker)) method = 1; QRgb *ptr; unsigned char c, m, y ,k; unsigned char *p; for (int i = 0; i < m_image.height(); i++) { ptr = (QRgb*) m_image.scanLine(i); if (method == 1) { for (int j = 0; j < m_image.width(); j++) { p = (unsigned char *) ptr; c = p[0]; m = p[1]; y = p[2]; k = p[3]; *ptr = qRgba(255 - c, 255 - m, 255 - y, 255 - k); ptr++; } } else if (method == 2) { for (int j = 0; j < m_image.width(); j++) { p = (unsigned char *) ptr; c = p[0]; m = p[1]; y = p[2]; k = p[3]; *ptr = qRgba(255 - c, 255 - m, 255 - y, k); ptr++; } } else { for (int j = 0; j < m_image.width(); j++) { p = (unsigned char *) ptr; c = p[0]; m = p[1]; y = p[2]; k = p[3]; *ptr = qRgba(y, m, c, k); ptr++; } } } isCMYK = true; } else isCMYK = false; if ( cinfo.output_components == 1 ) { QImage tmpImg = m_image.convertToFormat(QImage::Format_ARGB32); m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 ); QRgb *s; QRgb *d; for( int yi=0; yi < tmpImg.height(); ++yi ) { s = (QRgb*)(tmpImg.scanLine( yi )); d = (QRgb*)(m_image.scanLine( yi )); for(int xi=0; xi < tmpImg.width(); ++xi ) { (*d) = (*s); s++; d++; } } } } (void) jpeg_finish_decompress(&cinfo); fclose (infile); jpeg_destroy_decompress (&cinfo); m_imageInfoRecord.layerInfo.clear(); m_imageInfoRecord.BBoxX = 0; m_imageInfoRecord.BBoxH = m_image.height(); return (!m_image.isNull()); }