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; }
BOOL RenderWindow::InitGL(void) { Window::InitGL(); if(!image.LoadFromFile("edin01.bmp")) { MessageBox(NULL, "edin01.bmp 파일을 불러올 수 없습니다", "오류", MB_OK); return FALSE; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, image.GetWidth(), image.GetHeight(), 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, image.GetRawData()); glEnable(GL_TEXTURE_2D); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); return TRUE; }
void ImageProcessorDlg::Impl::test(ViewPane& view) { #if 0 CImageDecoderPtr d= photos_[0]->GetDecoder(); Dib bmp; CSize size(500,500); if (d->DecodeImg(bmp, size, false) != IS_OK) return; size = CSize(bmp.GetWidth(), bmp.GetHeight()); ExceptionInfo exc; GetExceptionInfo(&exc); Image* img= ConstituteImage(bmp.GetWidth(), bmp.GetHeight(), "RGB", CharPixel, bmp.GetBuffer(), &exc); if (img) { double radius= 10.0; double sigma= 1.0; double amount= 1.0; double threshold= 0.01; // Image* sharp= UnsharpMaskImage(img, radius, sigma, amount, threshold, &exc); int w= size.cy * 16 / 9; Image* sharp= LiquidRescaleImage(img, w, size.cy, 1.0, 0.0, &exc); if (sharp) { //ImageInfo ii; //GetImageInfo(&ii); //strcpy(sharp->filename, "c:\\sharp.img"); size.cx = sharp->columns; size.cy = sharp->rows; const PixelPacket* pix= AcquireImagePixels(sharp, 0, 0, size.cx, size.cy, &exc); Dib b(size.cx, size.cy, 24); for (int y= size.cy - 1; y >= 0; --y) { BYTE* line= b.LineBuffer(y); for (int x= 0; x < size.cx; ++x) { line[0] = pix->red; line[1] = pix->green; line[2] = pix->blue; line += 3; pix++; } } b.Swap(bmp); DestroyImage(sharp); } DestroyImage(img); } view.DisplayBitmap(bmp); bmp.Save(L"c:\\resized.bmp"); #endif }
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 } }