2025年3月27日 星期四 甲辰(龙)年 月廿六 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Other

heic(HEIF)格式图像处理(四)

时间:03-13来源:作者:点击数:41

读取heic格式图像

读取heic格式图像主要通过第三方库实现,首先创建读取的入口,在前面几期中讲过增加“打开”菜单按钮实现功能。

增加“打开图片”菜单:

  • QMenu *pMenu = menuBar()->addMenu(QStringLiteral("文件(&F)"));
  • QAction *pOpenFile = new QAction(QStringLiteral("打开图片(&O)"));
  • connect(pOpenFile, &QAction::triggered, this, &heicExample::OpenFile);
  • QAction *pExit = new QAction(QStringLiteral("退出(&Q)"));
  • pMenu->addAction(pOpenFile);
  • pMenu->addAction(pExit);

实现槽函数OpenFile:

  • void heicExample::OpenFile()
  • {
  • QString fileName = QFileDialog::getOpenFileName(
  • this,
  • tr("open image file"), "./",
  • tr("Image files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm *.heic);;All files (*.*)"));
  • if (pixItem && fileName != "")
  • {
  • m_graphicsScene->removeItem(pixItem); //将上一个图元从场景中移除,重新添加新的图元
  • delete pixItem;
  • pixItem = NULL;
  • for (int i = 0; i < m_loldrgb.length(); i++)
  • {
  • delete m_loldrgb[i];
  • m_loldrgb[i] = NULL;
  • }
  • m_loldrgb.clear();
  • }
  • if(fileName.contains(".heic"))
  • {
  • ReadHeif(fileName);
  • }
  • }

读取heic格式文件:

  • void heicExample::ReadHeif(QString filename)
  • {
  • filename = QDir::fromNativeSeparators(filename);
  • Array<ImageId> itemIds;
  • const char* outputFileName = "./abc";
  • // Make an instance of Heif Reader
  • auto *reader = Reader::Create();
  • if (reader->initialize(filename.toLatin1().data()) != ErrorCode::OK)
  • return;
  • // Verify that the file is HEIF format.
  • FileInformation fileInfo;
  • if (reader->getFileInformation(fileInfo) != ErrorCode::OK) {
  • cout << "Unable to get MetaBox! Wrong heif format." << endl;
  • return;
  • }
  • if (!(fileInfo.features & FileFeatureEnum::HasSingleImage ||
  • fileInfo.features & FileFeatureEnum::HasImageCollection)) {
  • cout << "The file don't have images in the Metabox. " << endl;
  • return;
  • }
  • uint64_t memoryBufferSize = 1024 * 1024;
  • ofstream outfile(outputFileName, ofstream::binary);
  • auto *memoryBuffer = new uint8_t[memoryBufferSize];
  • const auto metaBoxFeatures = fileInfo.rootMetaBoxInformation.features;
  • if (metaBoxFeatures & MetaBoxFeatureEnum::HasThumbnails)
  • {
  • //reader->getMasterImages(itemIds);
  • //const ImageId masterId = itemIds[0];
  • cout << "The file have Thumbnail." << endl;
  • // Thumbnail references ('thmb') are from the thumbnail image to the master image
  • //reader->getReferencedToItemListByType(masterId, "thmb", itemIds);
  • //const auto thumbnailId = itemIds[0];
  • //if (reader->getItemDataWithDecoderParameters(thumbnailId.get(), memoryBuffer, memoryBufferSize) == ErrorCode::OK)
  • //{
  • // ...decode data and display the image, show master image later
  • // EncodePlay(memoryBuffer, memoryBufferSize);
  • // return;
  • //}
  • }
  • // when the file is iPhone heic.
  • Array<ImageId> gridIds;
  • Grid gridData;
  • if (reader->getItemListByType("grid", gridIds) == ErrorCode::OK &&
  • (fileInfo.features & FileFeatureEnum::HasImageCollection) &&
  • reader->getItem(gridIds[0].get(), gridData) == ErrorCode::OK)
  • {
  • //return iphoneHeic(reader, gridData, outputFileName);
  • qDebug("iphone heic");
  • }
  • // The image have collections
  • if (fileInfo.features & FileFeatureEnum::HasImageCollection)
  • {
  • Array<ImageId> itemIds;
  • reader->getMasterImages(itemIds);
  • // all the image items
  • for (unsigned int i = 0; i < itemIds.size; i++) {
  • const ImageId masterId = itemIds[i];
  • if (reader->getItemDataWithDecoderParameters(
  • masterId.get(), memoryBuffer, memoryBufferSize) == ErrorCode::OK) {
  • DecoderConfiguration decodeConf; // struct containing
  • reader->getDecoderParameterSets(masterId.get(), decodeConf);
  • auto decoSpeInfo = decodeConf.decoderSpecificInfo;
  • for (unsigned int j = 0; j < decoSpeInfo.size; ++j) {
  • auto entry = decoSpeInfo[j];
  • outfile.write((const char *)entry.decSpecInfoData.begin(),
  • entry.decSpecInfoData.size);
  • }
  • outfile.write(reinterpret_cast<const char*>(memoryBuffer), memoryBufferSize);
  • if (i == 0)
  • {
  • EncodePlay(memoryBuffer, memoryBufferSize);
  • }
  • }
  • else { cout << "getItemDataWithDecoderParameters error" << endl; }
  • };
  • delete[] memoryBuffer;
  • Reader::Destroy(reader);
  • return;
  • }// The image only have 1 master image.
  • else if (fileInfo.features & FileFeatureEnum::HasSingleImage)
  • {
  • Array<ImageId> itemIds;
  • reader->getMasterImages(itemIds);
  • // Find the item ID of the first master image
  • const ImageId masterId = itemIds[0];
  • if (reader->getItemDataWithDecoderParameters(masterId.get(), memoryBuffer, memoryBufferSize) == ErrorCode::OK)
  • {
  • outfile.write(reinterpret_cast<const char*>(memoryBuffer), memoryBufferSize);
  • cout << "Get the master image" << endl;
  • // ffmpeg
  • // Get HEVC decoder configuration
  • EncodePlay(memoryBuffer, memoryBufferSize);
  • }
  • }
  • cout << "There no image in the file MetaBox! ";
  • Reader::Destroy(reader);
  • return;
  • }

通过EncodePlay函数解析heic格式图像:

  • void heicExample::EncodePlay(uint8_t * pData, int nDataLength)
  • {
  • AVPacket packet;
  • av_init_packet(&packet);
  • packet.data = (uint8_t*)pData;
  • packet.size = nDataLength;
  • packet.pts = (90000 / 25) * m_nFrameCounter++;
  • int ret = -1;
  • ret = avcodec_send_packet(m_pCodecContext, &packet);
  • // Again EAGAIN is not expected
  • if (ret < 0)
  • {
  • return;
  • }
  • while (!ret)
  • {
  • ret = avcodec_receive_frame(m_pCodecContext, m_pSrcFrame);
  • if (!ret)
  • {
  • //成功解码一帧
  • int w = m_pCodecContext->width;
  • int h = m_pCodecContext->height;
  • if (m_pRGBSwsContext == NULL)
  • {
  • m_pRGBSwsContext = sws_getContext(w, h, m_pCodecContext->pix_fmt, w, h, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
  • av_image_alloc(m_pFrameRGB->data, m_pFrameRGB->linesize, w, h, AV_PIX_FMT_RGB32, 1);
  • }
  • //转换图像格式,将解压出来的YUV420P的图像转换为RGB的图像
  • sws_scale(m_pRGBSwsContext, (uint8_t const * const *)m_pSrcFrame->data, m_pSrcFrame->linesize, 0, h, m_pFrameRGB->data, m_pFrameRGB->linesize);
  • //把这个RGB数据 用QImage加载
  • QImage tmpImg((uchar *)m_pFrameRGB->data[0], m_pCodecContext->width, m_pCodecContext->height, QImage::Format_RGB32);
  • image = tmpImg.copy();
  • //把图像复制一份 传递给界面显示
  • //emit signal_sendQImage(image);
  • //ui.label->resize(w, h);
  • //QImage img = image.scaled(ui.label->size(), Qt::KeepAspectRatio);
  • //ui.label->setPixmap(QPixmap::fromImage(img));
  • pixItem = new PixItem(QPixmap::fromImage(image));
  • //将该图元对象添加到场景中,并设置此图元在场景中的位置为中心(0,0)
  • m_graphicsScene->addItem(pixItem);
  • pixItem->setPos(0, 0);
  • //保存原来的颜色
  • for (int x = 0; x < image.width(); x++) {
  • for (int y = 0; y < image.height(); y++) {
  • QColor *oldColor = new QColor(image.pixel(x, y));
  • m_loldrgb.append(oldColor);
  • }
  • }
  • av_frame_unref(m_pSrcFrame);
  • }
  • }
  • }

通过ffmpeg解码heic格式,然后转换成RGB32格式,最后通过画布进行展示。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门