コード例 #1
0
ファイル: PSDDecoder.cpp プロジェクト: mikekov/ExifPro
ImageStat PSDDecoder::DecodeImg(Dib& bmp, CSize& img_size, bool resize, COLORREF rgb_back/*= RGB(255,255,255)*/)
{
	FileStream ifs;
	if (!ifs.Open(file_path_.c_str()))
		return IS_OPEN_ERR;

	if (!psd_.OpenHeader(ifs))
		return IS_FMT_NOT_SUPPORTED;

	if (!psd_.IsSupported())
		return IS_FMT_NOT_SUPPORTED;

	if (!psd_.PrepareReading(ifs, CalcReductionFactor(img_size, false)))
		return IS_FMT_NOT_SUPPORTED;

	// image may be reduced in size
	CSize size= psd_.GetResized();
	bmp.Create(size.cx, size.cy, 24);

	SetTotalLines(psd_.GetHeight());

	if (!LinesDecoded(0, false))
		return IS_DECODING_CANCELLED;

	while (psd_.GetScanLine() < psd_.GetHeight())
	{
		psd_.ReadNextLine(ifs, bmp, 0);

		if (IsICCEnabled())
			ApplyICC(bmp.LineBuffer(psd_.GetScanLine() - 1), bmp.GetWidth(), bmp.GetColorComponents());

		int scan_line= psd_.GetScanLine();

		// report progress
		if (!LinesDecoded(scan_line, scan_line == psd_.GetHeight()))
			return IS_DECODING_CANCELLED;
	}

	if (resize)
		bmp.ResizeToFit(img_size, Dib::RESIZE_CUBIC);

	return IS_OK;
}
コード例 #2
0
ファイル: BMPDecoder.cpp プロジェクト: mikekov/ExifPro
ImageStat BMPDecoder::DecodeImg(Dib& dib, CSize& img_size, bool resize, COLORREF rgb_back/*= RGB(255,255,255)*/)
{
	BMPReader bmp;

	ImageStat stat= bmp.Open(filePath_.c_str());
	if (stat != IS_OK)
		return stat;

	img_size_ = bmp.GetSize();

	if (!bmp.IsSupported())
		return IS_FMT_NOT_SUPPORTED;

	//CSize size2= img_size;
	//if (ImageStat stat= png_.PrepareReading(CalcReductionFactor(size2, false)))
	//	return stat;

	// image may be reduced in size
	//CSize size= png_.GetResized();
	//dib.Create(size.cx, size.cy, 24);

	SetTotalLines(img_size_.cy);

	if (!LinesDecoded(0, false))
	{
//		png_.Close();
		return IS_DECODING_CANCELLED;
	}

	stat = bmp.ReadImage(dib);
	if (stat != IS_OK)
		return stat;
/*
	while (png_.GetPass() < png_.GetNoOfPasses())
	{
		while (png_.GetScanLine() < png_.GetHeight())
		{
			png_.ReadNextLine(bmp);

			if (png_.GetPass() == png_.GetNoOfPasses() - 1)
			{
				int scan_line= png_.GetScanLine();

				// report progress
				if (!LinesDecoded(scan_line, scan_line == png_.GetHeight()))
				{
					png_.Close();
					return IS_DECODING_CANCELLED;
				}
			}
		}

		png_.NextPass();
	}
*/
	if (!LinesDecoded(img_size_.cy, true))
		return IS_DECODING_CANCELLED;

	if (resize && img_size != img_size_)
		dib.ResizeToFit(img_size, Dib::RESIZE_CUBIC);

	return IS_OK;
}
コード例 #3
0
ファイル: CatalogImages.cpp プロジェクト: mikekov/ExifPro
void CatalogImages::Impl::ProcessFiles(int img_size, int jpeg_compression_level)
{
    const size_t count= files_.size();

    counter_ = 0;

    for (size_t i= 0; i < count; ++i)
    {
        if (parentWnd_)
            ::PostMessage(parentWnd_, MESSAGE, i, IMG_PROCESSING);

        if (break_)
            return;

        const Path& path= files_[i].first;

        PhotoFactory::CreateFn fn= 0;
        int id= 0;

        if (!GetPhotoFactory().MatchPhotoType(path.GetExtension(), fn, id))
        {
            ASSERT(false);
            continue;
        }

        SmartPhotoPtr photo(fn());

        try
        {
            CatalogImgRecord img;

//			ExifBlock exif;
//			exif.clear();

            bool has_exif= photo->Scan(path.c_str(), img.exif_, false, nullptr);	// scan image to find EXIF data

            if (!has_exif && readOnlyPhotosWithEXIF_)
                continue;

            if (!has_exif || photo->GetDateTime().is_not_a_date_time())
                ReadFileTimeStamp(*photo, path);

            uint64 fileLength= 0;
            // write to db

            img.type_ = id;

            // get file length and last write time
            {
                WIN32_FIND_DATA findFileData;
                HANDLE find= ::FindFirstFile(path.c_str(), &findFileData);
                if (find != INVALID_HANDLE_VALUE)
                {
                    VERIFY(::FindClose(find));
                    fileLength = uint64(findFileData.nFileSizeLow) + (uint64(findFileData.nFileSizeHigh) << 32);

                    img.time_stamp_ = findFileData.ftLastWriteTime;
                    img.access_time_ = findFileData.ftLastAccessTime;
                    img.creation_time_ = findFileData.ftCreationTime;
                    img.file_attribs_ = findFileData.dwFileAttributes;
                }
            }
//			uint64 fileLength= path.GetFileLength();

            //photo->dir_visited_ = static_cast<uint32>(dir_visited);
            photo->SetFileSize(fileLength);
            photo->SetPhotoName(path.GetFileName());
            photo->SetPhysicalPath(path);
            photo->exif_data_present_ = has_exif;

            //			SetAutoRotationFlag(photo.get());

            img.path_ = String2WStr(path);
            img.make_ = String2WStr(photo->GetMake());
            img.model_ = String2WStr(photo->GetModel());
            img.orientation_ = photo->OrientationField();

            img.file_size_ = fileLength;
//			find.GetLastWriteTime(&img.time_stamp_);
            //photo->index_.Serialize(img.buf_index_);

            // verify this: ===========
            //		img.jpeg_offset_ = photo->jpeg_offset_;
            // HACK: this is orientation extracted from CRW file; when reading info from
            // cache CRW is not scanned, so orientation cannot be set
            img.exif_orientation_ = has_exif ? 0u : photo->OrientationField();
            // =========================

            // EXIF block
            img.has_exif_ = has_exif;
//			img.exif_ifd_offset_ = static_cast<int32>(exif.ifd0Start);
//			if (exif.is_raw)
//				img.exif_type_ = exif.bigEndianByteOrder ?
//					CatalogImgRecord::RAW_MM_EXIF_BLOCK : CatalogImgRecord::RAW_II_EXIF_BLOCK;
//			else
//				img.exif_type_ = CatalogImgRecord::JPEG_EXIF_BLOCK;
//			img.exif_.swap(exif.exif_buffer);

            // prepare preview
            Dib bmp;
            CSize thumbnail_size(img_size, img_size);
            CImageDecoderPtr decoder= photo->GetDecoder();
            bool ycbcr_image= true;
            ImageStat stat= decoder->DecodeImgToYCbCr(bmp, thumbnail_size, true);
            if (stat != IS_OK)
            {
                ycbcr_image = false;

                if (stat == IS_OPERATION_NOT_SUPPORTED)
                    stat = decoder->DecodeImg(bmp, thumbnail_size, true);
            }

            if (stat != IS_OK || !bmp.IsValid())
            {
                failed_.push_back(path);
                continue;
            }

            // if EXIF indicates rotation and photo is already physically rotated AND exif reset EXIF orientation
            // flag back to normal to avoid problems later on...
            PhotoInfo::ImgOrientation orient= photo->GetOrientation();
            if ((orient == PhotoInfo::ORIENT_90CCW || orient == PhotoInfo::ORIENT_90CW) &&
                    photo->GetWidth() > photo->GetHeight() && bmp.GetWidth() < bmp.GetHeight())
            {
                //photo->orientation_ = 0;
                std::swap(img.img_width_, img.img_height_);
                uint32 w= photo->GetWidth();
                uint32 h= photo->GetHeight();
                photo->SetSize(h, w);
            }
            else if ((orient == PhotoInfo::ORIENT_NORMAL || orient == PhotoInfo::ORIENT_NO_INFO ||
                      orient == PhotoInfo::ORIENT_UNKNOWN) &&
                     photo->GetWidth() > photo->GetHeight() && bmp.GetWidth() < bmp.GetHeight())
            {
                // orientation is 'normal', but reported size and size of decoded image do not agree
                uint32 w= photo->GetWidth();
                uint32 h= photo->GetHeight();
                photo->SetSize(h, w);
            }

            img.photo_width_ = photo->GetWidth();
            img.photo_height_ = photo->GetHeight();

            //TODO: convert non-ycbcr from rgb if needed

            // calculate 'index' using YCbCr image
            photo->index_.CalcHistogram(bmp);
            photo->index_.Serialize(img.index_);

            // now to RGB
            if (ycbcr_image)
                bmp.ConvertYCbCr2RGB();

            Dib thm;	// little thumbnail
            if (img_size > 160)
                bmp.ResizeToFit(CSize(160, 160), Dib::RESIZE_HALFTONE, thm);

            CSize size= bmp.GetSize();
            int big= img_size;
            if (size.cx > big || size.cy > big)
                bmp.ResizeToFit(CSize(big, big), Dib::RESIZE_HALFTONE);

            img.img_width_ = bmp.GetWidth();
            img.img_height_ = bmp.GetHeight();

            // compress preview into JPEG
            JPEGEncoder enc(jpeg_compression_level, false, false);

            if (thm.IsValid())
            {
                // we have both little thumbnail image and preview image
                {
                    CMemoryDataDestination memdest;
                    enc.Encode(memdest, &thm);
                    memdest.SwapJPEG(img.thumbnail_);
                }
                {
                    CMemoryDataDestination memdest;
                    enc.Encode(memdest, &bmp);
                    memdest.SwapJPEG(img.preview_);
                }
            }
            else
            {
                // only small preview available;
                // store it in the thumbnail leaving preview field empty

                CMemoryDataDestination memdest;
                enc.Encode(memdest, &bmp);
                memdest.SwapJPEG(img.thumbnail_);

                img.preview_.clear();
            }

            // IPTC present?
            //if (photo->IPTC_.get())
            //	img.iptc_.reset(photo->IPTC_.release());
            if (photo->HasMetadata())
            {
                img.iptc_.reset(new IPTCRecord());
                photo->GetIPTCInfo(*img.iptc_);
            }

            img.description_ = photo->GetExifDescription();
            img.marker_index_ = photo->GetFileTypeIndex();

            //TODO: store XMP too!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//TODO:
//	grab tags;
//	and description;
            //			EliminateNonPrintableChars(photo->photo_desc_);
            //			PostProcessTime(photo.get());

            CatalogHeader::DirPtr dir= files_[i].second;
            img.dir_visited_ = dir->id_;

            // add/modify record
            std::vector<uint8> buf;
            img.Serialize(buf, 1);
            uint64 record_offset= dbImages_.Append(buf);

            // examine tags
            if (!photo->GetTags().empty())	// has tags?
            {
                PhotoTags::const_iterator end= photo->GetTags().end();

                for (PhotoTags::const_iterator it = photo->GetTags().begin(); it != end; ++it)
                    tags_[*it].push_back(record_offset);
            }

            if (dir->records_.empty())
                dir->records_.reserve(dir->reserved_capacity_);

            if (dir->records_.size() < dir->reserved_capacity_)
                dir->records_.push_back(record_offset);
            else
            {
                ASSERT(false);
                continue;
            }

            ++counter_;
        }
        catch (MemPointer::MemPtrException&)
        {
            CString msg= _T("Error parsing file: ");
            msg += path.c_str();
            ::ShowMessageBox(msg);
        }
        catch (CMemoryException*)
        {
            CString msg= _T("Out of memory reading file: ");
            msg += path.c_str();
            ::ShowMessageBox(msg);
        }
        catch (JPEGException& ex)
        {
            CString msg= _T("Error processing file: ");
            msg += path.c_str();
            msg += _T("\n\n");
            msg += ex.GetMessage();
            ::ShowMessageBox(msg);
        }
#ifndef _DEBUG
        catch (...)
        {
//			ASSERT(false);
        }
#endif

    }
}