C++ Bayer图像格式,使用GDAL进行格式转换。
Bayer图像说明
1、Bayer图像格式介绍
bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像。
对于彩色图像,需要采集多种最基本的颜色,如rgb三种颜色,最简单的方法就是用滤镜的方法,红色的滤镜透过红色的波长,绿色的滤镜透过绿色的波长,蓝色的滤镜透过蓝色的波长。如果要采集rgb三个基本色,则需要三块滤镜,这样价格昂贵,且不好制造,因为三块滤镜都必须保证每一个像素点都对齐。当用bayer格式的时候,很好的解决了这个问题。bayer 格式图片在一块滤镜上设置的不同的颜色,通过分析人眼对颜色的感知发现,人眼对绿色比较敏感,所以一般bayer格式的图片绿色格式的像素是是r和g像素的和。
另外,Bayer格式是相机内部的原始图片, 一般后缀名为.raw。很多软件都可以查看, 比如PS。我们相机拍照下来存储在存储卡上的.jpeg或其它格式的图片, 都是从.raw格式转化过来的。如下图,为bayer色彩滤波阵列,由一半的G,1/4的R,1/4的B组成。
2、Bayer图像传感原理
图像传感器的结构如下所示,每一个感光像素之间都有金属隔离层,光纤通过显微镜头,在色彩滤波器过滤之后,投射到相应的漏洞式硅的感光元件上。
当Image Sensor往外逐行输出数据时,像素的序列为GRGRGR…/BGBGBG…(顺序RGB)。这样阵列的Sensor设计,使得RGB传感器减少到了全色传感器的1/3,如下所示。
3、bayer格式插值红蓝算法实现
每一个像素仅仅包括了光谱的一部分,必须通过插值来实现每个像素的RGB值。为了从Bayer格式得到每个像素的RGB格式,我们需要通过插值填补缺失的2个色彩。插值的方法有很多(包括领域、线性、3*3等),速度与质量权衡,最好的线性插值补偿算法。其中算法如下:
R和B通过线性领域插值,但这有四种不同的分布,如下图所示:
A B
C D
在(a)与(b)中,R和B分别取邻域的平均值。
在(c)与(d)中,取领域的4个B或R的均值作为中间像素的B值。
4、bayer格式插值绿算法实现
E F
由于人眼对绿光反应最敏感,对紫光和红光则反应较弱,因此为了达到更好的画质,需要对G特殊照顾。在上述(c)与(d)中,扩展开来就是上图的(e)与(f)中间像素G的取值,者也有一定的算法要求,不同的算法效果上会有差异。经过相关的研究,
(e)中间像素G值的算法如下:
(f)中间像素G值的算法如下:
CMOS摄像头这部分转换是在内部用ADC或者ISP完成的,生产商为了降低成本必然会使得图像失真。当然用外部处理器来实现转换,如果处理器的速度足够NB,能够胜任像素的操作,用上面的算法来进行转换,皆大欢喜。不过上述算法将直接成倍提高了算法的复杂度,速度上将会有所限制。因此为了速度的提成,可以直接通过来4领域G取均值来中间像素的G值,将会降低一倍的速率,而在性能上差之甚微,算法如下:
如果能够通过损失图像的额质量,来达到更快的速度,还可以取G1、G2的均值来实现,但是这样的做法会导致边沿以及跳变部分的失真。
将Bayer格式转换为tif格式
//全部.h文件
#include <iostream>
#include <vector>
#include <fstream>
#include <gdal_priv.h>
#include <gdalwarper.h>
#include <gdal.h>
#include <stdio.h>
#include <stdlib.h>
#include "j2k_mem_advance.h"
#include "format_defs.h"
#include "j2k_mem.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/io.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <memory>
#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <time.h>
#include <thread>
#include <stdio.h>
#include <string.h>
#include "TinyXML.h"using namespace std;
//此头文件应该是必须的部分
#include <iostream>
#include <fstream>
#include <gdal_priv.h>
#include <gdalwarper.h>
#include <gdal.h>
#include <stdio.h>
#include <stdlib.h>using namespace std;//核心代码部分
//将.dat文件读取后进行gbbr转换,最后转码为TIF文件
bool Anal_pixel(string strFilePath, string strSavePath, long nWidth, long nHeight, int nType)
{// TODO: 在此添加控件通知处理程序代码GDALAllRegister();CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //支持中文路径if (strFilePath == ""){return false;}const char* pszFormat = "GTIFF";GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);if (!poDriver) {return false;}//long width = 7920;//long height = 6004;long long width = nWidth;long long height = nHeight;GDALDataType gdal_data_type = GDT_UInt16;unsigned short* pData = new unsigned short[width * height];fstream sf;sf.open(strFilePath, ios::in | ios::binary);//打开文件,供读sf.seekg(0, ios::beg);//byte *bTemp = new byte[2];unsigned char* bTemp = new unsigned char[2];for (int i = 0; i < height * width; i++){sf.read((char*)&bTemp[0], sizeof(unsigned char));sf.read((char*)&bTemp[1], sizeof(unsigned char));pData[i] = bTemp[0] * 256 + bTemp[1];//char pBuff[8];//sprintf(pBuff, "%04x", pData[i]);//int isdsd = 0;}sf.close();delete[] bTemp;//----------------------解析
#pragma region 解析PointInfo** cArryAllPoint; // 二维数组cArryAllPoint = (PointInfo**)malloc(height * sizeof(PointInfo*));//height 行for (int i = 0; i < height; i++) {cArryAllPoint[i] = (PointInfo*)malloc(width * sizeof(PointInfo));//width 列}//读取文件,将文件中的数值填充for (long long y = 0; y < height; y++){for (long long x = 0; x < width / 2; x++){cArryAllPoint[y][2 * x].Point_X = 2 * x;cArryAllPoint[y][2 * x].Point_Y = y;cArryAllPoint[y][2 * x + 1].Point_X = 2 * x + 1;cArryAllPoint[y][2 * x + 1].Point_Y = y;if (y % 2 == 0){cArryAllPoint[y][2 * x].Point_B = pData[y * width / 4 + x + height * width * 1 / 2];//BcArryAllPoint[y][2 * x + 1].Point_G = pData[y * width / 2 + x];//G}else{cArryAllPoint[y][2 * x].Point_G = pData[y * width / 2 + x];//GcArryAllPoint[y][2 * x + 1].Point_R = pData[(y - 1) * width / 4 + x + height * width * 3 / 4];//R}}}delete[] pData;//释放内存//计算RGB值unsigned short R1, R2, R3, R4, B1, B2, B3, B4, G1, G2, G3, G4;for (long long y = 0; y < height; y++)//初始化数据 {for (long long x = 0; x < width; x++){if (y % 2 == 0){if (x % 2 == 0){if (x == 0){if (y == 0){R1 = 0;R2 = 0;R3 = 0;R4 = cArryAllPoint[y + 1][x + 1].Point_R;G1 = 0;G2 = 0;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = cArryAllPoint[y + 1][x].Point_G;}else if (y == height - 1){R1 = 0;R2 = 0;R3 = cArryAllPoint[y - 1][x + 1].Point_R;R4 = 0;G1 = 0;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = 0;}else{R1 = 0;R2 = 0;R3 = cArryAllPoint[y - 1][x + 1].Point_R;R4 = cArryAllPoint[y + 1][x + 1].Point_R;G1 = 0;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = cArryAllPoint[y + 1][x].Point_G;}}else if (x == width - 1){if (y == 0){R1 = cArryAllPoint[y + 1][x - 1].Point_R;R2 = 0;R3 = 0;R4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = 0;G3 = 0;G4 = cArryAllPoint[y + 1][x].Point_G;}else if (y == height - 1){R1 = 0;R2 = cArryAllPoint[y - 1][x - 1].Point_R;R3 = 0;R4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = 0;G4 = 0;}else{R1 = cArryAllPoint[y + 1][x - 1].Point_R;R2 = cArryAllPoint[y - 1][x - 1].Point_R;R3 = 0;R4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = 0;G4 = cArryAllPoint[y + 1][x].Point_G;}}else{if (y == 0){R1 = cArryAllPoint[y + 1][x - 1].Point_R;R2 = 0;R3 = 0;R4 = cArryAllPoint[y + 1][x + 1].Point_R;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = 0;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = cArryAllPoint[y + 1][x].Point_G;}else if (y == height - 1){R1 = 0;R2 = cArryAllPoint[y - 1][x - 1].Point_R;R3 = cArryAllPoint[y - 1][x + 1].Point_R;R4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = 0;}else{R1 = cArryAllPoint[y + 1][x - 1].Point_R;R2 = cArryAllPoint[y - 1][x - 1].Point_R;R3 = cArryAllPoint[y - 1][x + 1].Point_R;R4 = cArryAllPoint[y + 1][x + 1].Point_R;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = cArryAllPoint[y + 1][x].Point_G;}}cArryAllPoint[y][x].Point_R = (R1 + R2 + R3 + R4) / 4;cArryAllPoint[y][x].Point_G = (G1 + G2 + G3 + G4) / 4;}else{//unsigned short R1, R2, B1, B2;//G//G1,R2,G4//B1,G ,B2//G2,R1,G3//R1 = cArryAllPoint.GetAt(y - 1)->GetAt(x).Point_R;//R2 = cArryAllPoint.GetAt(y + 1)->GetAt(x).Point_R;//B1 = cArryAllPoint.GetAt(y)->GetAt(x - 1).Point_B;//B2 = cArryAllPoint.GetAt(y)->GetAt(x + 1).Point_B;if (x == 0){if (y == 0){R1 = 0;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = 0;B2 = cArryAllPoint[y][x + 1].Point_B;}else if (y == height - 1){R1 = cArryAllPoint[y - 1][x].Point_R;R2 = 0;B1 = 0;B2 = cArryAllPoint[y][x + 1].Point_B;}else{R1 = cArryAllPoint[y - 1][x].Point_R;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = 0;B2 = cArryAllPoint[y][x + 1].Point_B;}}else if (x == width - 1){if (y == 0){R1 = 0;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = 0;}else if (y == height - 1){R1 = cArryAllPoint[y - 1][x].Point_R;R2 = 0;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = 0;}else{R1 = cArryAllPoint[y - 1][x].Point_R;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = 0;}}else{if (y == 0){R1 = 0;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = cArryAllPoint[y][x + 1].Point_B;}else if (y == height - 1){R1 = cArryAllPoint[y - 1][x].Point_R;R2 = 0;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = cArryAllPoint[y][x + 1].Point_B;}else{R1 = cArryAllPoint[y - 1][x].Point_R;R2 = cArryAllPoint[y + 1][x].Point_R;B1 = cArryAllPoint[y][x - 1].Point_B;B2 = cArryAllPoint[y][x + 1].Point_B;}}cArryAllPoint[y][x].Point_R = (R1 + R2) / 2;cArryAllPoint[y][x].Point_B = (B1 + B2) / 2;}}else{if (x % 2 == 0){//unsigned short R1, R2, B1, B2;//G//G1,B2,G4//R1,G ,R2//G2,B1,G3//R1 = cArryAllPoint.GetAt(y)->GetAt(x - 1).Point_R;//R2 = cArryAllPoint.GetAt(y)->GetAt(x + 1).Point_R;//B1 = cArryAllPoint.GetAt(y - 1)->GetAt(x).Point_B;//B2 = cArryAllPoint.GetAt(y + 1)->GetAt(x).Point_B;if (x == 0){if (y == 0){R1 = 0;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = 0;B2 = cArryAllPoint[y + 1][x].Point_B;}else if (y == height - 1){R1 = 0;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = 0;}else{R1 = 0;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = cArryAllPoint[y + 1][x].Point_B;}}else if (x == width - 1){if (y == 0){R1 = cArryAllPoint[y][x - 1].Point_R;R2 = 0;B1 = 0;B2 = cArryAllPoint[y + 1][x].Point_B;}else if (y == height - 1){R1 = cArryAllPoint[y][x - 1].Point_R;R2 = 0;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = 0;}else{R1 = cArryAllPoint[y][x - 1].Point_R;R2 = 0;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = cArryAllPoint[y + 1][x].Point_B;}}else{if (y == 0){R1 = cArryAllPoint[y][x - 1].Point_R;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = 0;B2 = cArryAllPoint[y + 1][x].Point_B;}else if (y == height - 1){R1 = cArryAllPoint[y][x - 1].Point_R;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = 0;}else{R1 = cArryAllPoint[y][x - 1].Point_R;R2 = cArryAllPoint[y][x + 1].Point_R;B1 = cArryAllPoint[y - 1][x].Point_B;B2 = cArryAllPoint[y + 1][x].Point_B;}}cArryAllPoint[y][x].Point_R = (R1 + R2) / 2;cArryAllPoint[y][x].Point_B = (B1 + B2) / 2;}else{//unsigned short B1, B2, B3, B4, G1, G2, G3, G4;//R//B1,G4,B4//G1,R ,G3//B2,G2,B3//B1 = cArryAllPoint.GetAt(y + 1)->GetAt(x - 1).Point_B;//B2 = cArryAllPoint.GetAt(y - 1)->GetAt(x - 1).Point_B;//B3 = cArryAllPoint.GetAt(y - 1)->GetAt(x + 1).Point_B;//B4 = cArryAllPoint.GetAt(y + 1)->GetAt(x + 1).Point_B;//G1 = cArryAllPoint.GetAt(y)->GetAt(x - 1).Point_G;//G2 = cArryAllPoint.GetAt(y - 1)->GetAt(x).Point_G;//G3 = cArryAllPoint.GetAt(y)->GetAt(x + 1).Point_G;//G4 = cArryAllPoint.GetAt(y + 1)->GetAt(x).Point_G;if (x == 0){//不存在 X=0}else if (x == width - 1){if (y == 0){//不存在 Y=0}else if (y == height - 1){B1 = 0;B2 = cArryAllPoint[y - 1][x - 1].Point_B;B3 = 0;B4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = 0;G4 = 0;}else{B1 = cArryAllPoint[y + 1][x - 1].Point_B;B2 = cArryAllPoint[y - 1][x - 1].Point_B;B3 = 0;B4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = 0;G4 = cArryAllPoint[y + 1][x].Point_G;}}else{if (y == 0){//不存在 Y=0}else if (y == height - 1){B1 = 0;B2 = cArryAllPoint[y - 1][x - 1].Point_B;B3 = cArryAllPoint[y - 1][x + 1].Point_B;B4 = 0;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = 0;}else{B1 = cArryAllPoint[y + 1][x - 1].Point_B;B2 = cArryAllPoint[y - 1][x - 1].Point_B;B3 = cArryAllPoint[y - 1][x + 1].Point_B;B4 = cArryAllPoint[y + 1][x + 1].Point_B;G1 = cArryAllPoint[y][x - 1].Point_G;G2 = cArryAllPoint[y - 1][x].Point_G;G3 = cArryAllPoint[y][x + 1].Point_G;G4 = cArryAllPoint[y + 1][x].Point_G;}}cArryAllPoint[y][x].Point_B = (B1 + B2 + B3 + B4) / 4;cArryAllPoint[y][x].Point_G = (G1 + G2 + G3 + G4) / 4;}}}}//整合到pDataRGB中//unsigned char * pDataRGB = new unsigned char[width * height * 3];unsigned short** newbuffs = new unsigned short* [3]; // 1, 2, 3 : r g b newbuffs[0] = new unsigned short[width * height];newbuffs[1] = new unsigned short[width * height];newbuffs[2] = new unsigned short[width * height];double dTemp;for (long long y = 0; y < height; y++)//初始化数据{for (long long x = 0; x < width; x++){dTemp = (double)cArryAllPoint[y][x].Point_R;newbuffs[0][y * width + x] = (unsigned short)dTemp;dTemp = (double)cArryAllPoint[y][x].Point_G;newbuffs[1][y * width + x] = (unsigned short)dTemp;dTemp = (double)cArryAllPoint[y][x].Point_B;newbuffs[2][y * width + x] = (unsigned short)dTemp;}}double minDN[3] = { 0 };//统计最小的DN值double maxDN[3] = { 0 };//统计最大的DN值//释放内存 cArryAllPointfor (int i = 0; i < height; i++){delete[] cArryAllPoint[i];}free(cArryAllPoint);//将原数据进行拉伸放大for (long long m = 0; m < height; m++){for (long long n = 0; n < width; n++){for (long long i = 0; i < 3; i++){if (newbuffs[i][m * width + n] < minDN[i])minDN[i] = newbuffs[i][m * width + n];if (newbuffs[i][m * width + n] > maxDN[i])maxDN[i] = newbuffs[i][m * width + n];}}}for (long long i = 0; i < 3; i++){for (long long m = 0; m < height*width; m++){newbuffs[i][m] = (newbuffs[i][m] - minDN[i]) * 1.0 / (maxDN[i] - minDN[i]) * 65535;}}#pragma endregionif (nType == 0)//拉伸后的图像{char** papszOptions = nullptr;papszOptions = CSLSetNameValue(papszOptions, "INTERLEAVE", "BAND");papszOptions = CSLSetNameValue(papszOptions, "BIGTIFF", "IF_NEEDED");const char* pszDstFilename = strSavePath.c_str();GDALDataset* poDstDS = poDriver->Create(pszDstFilename, width, height, 3, GDT_UInt16, papszOptions);if (!poDstDS) {for (int i = 0; i < 3; i++){delete[] newbuffs[i];}free(newbuffs);return false;}int bandMap[3] = { 1, 2, 3 };for (int i = 0; i < 3; i++){poDstDS->GetRasterBand(i + 1)->RasterIO(GF_Write, 0, 0, width, height, newbuffs[i], width, height, GDT_UInt16, 0, 0, 0);delete[] newbuffs[i];}free(newbuffs);GDALClose((GDALDatasetH)poDstDS);}else{//针对原图16位的值进行高8位、低8位、中8位的转换。unsigned char** newbuffs1 = new unsigned char* [3]; // 1, 2, 3 : r g b newbuffs1[0] = new unsigned char[width * height];newbuffs1[1] = new unsigned char[width * height];newbuffs1[2] = new unsigned char[width * height];for (long long i = 0; i < 3; i++){for (long long m = 0; m < height; m++){for (long long n = 0; n < width; n++){char pBuff[4], pBuff2[8];if (nType == 1)//高8{newbuffs1[i][m * width + n] = newbuffs[i][m * width + n] / 4;//------G8}else if (nType == 2)//中8{newbuffs1[i][m * width + n] = newbuffs[i][m * width + n] / 2;//-------M8}else if (nType == 3)//低8{newbuffs1[i][m * width + n] = newbuffs[i][m * width + n];//------D8}}}}char** papszOptions = nullptr;papszOptions = CSLSetNameValue(papszOptions, "INTERLEAVE", "BAND");papszOptions = CSLSetNameValue(papszOptions, "BIGTIFF", "IF_NEEDED");const char* pszDstFilename = strSavePath.c_str();GDALDataset* poDstDS = poDriver->Create(pszDstFilename, width, height, 3, GDT_Byte, papszOptions);if (!poDstDS) {for (int i = 0; i < 3; i++){delete[] newbuffs[i];delete[] newbuffs1[i];}return false;}int bandMap[3] = { 1, 2, 3 };for (int i = 0; i < 3; i++){poDstDS->GetRasterBand(i + 1)->RasterIO(GF_Write, 0, 0, width, height, newbuffs1[i], width, height, GDT_Byte, 0, 0, 0);delete[] newbuffs[i];delete[] newbuffs1[i];}GDALClose((GDALDatasetH)poDstDS);}return true;
}
第一次书写博客会有些许乱,有需求的可以私我或者留言询问具体问题。
参考文件:
感谢作者:
淇淇宝贝 https://www.cnblogs.com/qiqibaby/p/5267566.html
C++ Bayer图像格式,使用GDAL进行格式转换。相关推荐
- MIPI RAW和YUV常见图像格式的解析、格式转换和看图软件
设计初衷 在ISP的图像算法开发中,经常会涉及到YUV.RAW等格式的图像.例如,在YUV域,经常会涉及到I420.NV12和P010等数据格式之间的转换.在RAW域,又会经常涉及到MIPI RAW等 ...
- 图像格式及Matlab的格式转换
1. matlab图像保存说明 matlab中读取图片后保存的数据是uint8类型(8位无符号整数,即1个字节),以此方式存储的图像称作8位图像,好处相比较默认matlab数据类型双精度浮点doubl ...
- Python:图片格式转换
JPG格式图片转PNG格式 png和jpg最大的不同点在于png支持alpha通道,也就是我们说的透明通道,而jpg是不支持透明通道的,这就使得png格式在某些场合具有特殊的用途. RGBA是代表Re ...
- DDSM数据库转换图像格式——LJPEG转为PNG格式
Digital Database for Screening Mammography (DDSM)数据库是一个非常大的乳腺图像数据库,有一万多张图像,但是图像格式是LJPEG,现有的图像软件(如pho ...
- JAVA调用GDAL实现影像格式转换,以tif to jpg为例
前言 本文简单实现java调用GDAL实现影像格式转换. package Marcus.com;import org.gdal.gdal.Dataset; import org.gdal.gdal.D ...
- FFmpeg学习4:音频格式转换
前段时间,在学习试用FFmpeg播放音频的时候总是有杂音,网上的很多教程是基于之前版本的FFmpeg的,而新的FFmepg3中audio增加了平面(planar)格式,而SDL播放音频是不支持平面格式 ...
- 常用图像格式(PNG,JPG)到SGI图像格式(RGB,BW)的转换
常用图像格式(PNG,JPG)到SGI图像格式(RGB,BW)的转换 网站链接 根据该网站的描述和给的相应例子,自己改写了一个把png,jpg等常用格式的图片转化为rgb,bw格式的代码. #incl ...
- c语言bmp转换jpeg_PDF格式转换工具
Cisdem PDF Converter OCR for Mac是一款Mac平台的PDF格式转换工具,可以帮助我们将PDF格式的文件转换成Word, Text, Excel, ePub, Keynot ...
- 使用GDAL下载并转换SRTM的DEM数据(一)
有时候需要用到DEM数据,常用的免费的DEM数据就是SRTM的DEM数据. SRTM数据主要是由美国太空总署(NASA)和国防部国家测绘局(NIMA)联合测量的,SRTM的全称是Shuttle Rad ...
- 如何利用 onlyoffice 实现文档格式转换
目录 前言 正文 启动 onlyoffice 服务 API 接口介绍 转换列表 请求示例 结尾 前言 日常生活和工作中,文档格式转换应该是很常见的需求.面对这样的需求,我们技术男有没有属于自己的好方法 ...
最新文章
- 五大晶元厂的内存型号命名方式
- C++实现删除字符串中所有重复出现的字符
- JAVA虚拟机体系结构
- python中模块(Module)和包(Package)的区别 (导入模块、导入包)(import导包)
- Vue——全局element-resize-detector监听DOM元素
- Map map = request.getParameterMap(); BeanUtils.populate(bean, map);对前端表单的迅速封装与判断
- 计算机数媒专业优势,27所院校新开设数字媒体艺术专业,“数媒”专业为什么这么火?...
- edite not the main type
- springboot系列二、springboot项目搭建
- 腾讯云独立模式账号引入接口
- The Semantics of Constructors(拷贝构造函数之编译背后的行为)
- 运动控制器RTEX总线使用入门
- zigbee学习之JN5169 串口UARTs
- SharePoint 集成PowerApps和Flow教程(一,搭建PowerApps 环境)
- 电脑开机显示器黑屏是什么原因,电脑显示器黑屏怎么办
- 莫纳什大学计算机专业录取要求,2020年莫纳什大学计算机信息硕士申请条件
- 华为OD机试用Python实现 -【查找树中的元素 or 查找二叉树节点】(2023-Q1 新题)
- 使用证件照api接口快速上线证件照业务-超详细!
- OpenCL编程初探
- 唇语识别!AI 领域的下一个万亿市场?