bus*_*ard 4 c++ arrays png bitmap
所以我发现这个关于我的问题的链接,但它是针对c#
我有一个变量int数组.我现在称它为"pix []",它可以是3到256之间的任何大小,之后可能更大.
我现在想做的是将其转换为像素图像.我仍然是一个noobin c ++,请原谅我.我试图下载一些使libpng更容易使用的库,但它们似乎没有工作(ubuntu,code :: blocks)所以我有以下问题:
1)如何创建新的位图(哪个libaries,哪个命令)?
2)如何填写"pix []"的信息?
3)我该如何保存?
如果它是一个问题的转贴我也很高兴链接;)
这是我到目前为止所做的工作,谢谢你的帮助.
int main(){
FILE *imageFile;
int x,y,pixel,height=2,width=3;
imageFile=fopen("image.pgm","wb");
if(imageFile==NULL){
perror("ERROR: Cannot open output file");
exit(EXIT_FAILURE);
}
fprintf(imageFile,"P3\n"); // P3 filetype
fprintf(imageFile,"%d %d\n",width,height); // dimensions
fprintf(imageFile,"255\n"); // Max pixel
int pix[100] {200,200,200, 100,100,100, 0,0,0, 255,0,0, 0,255,0, 0,0,255};
fwrite(pix,1,18,imageFile);
fclose(imageFile);
}
Run Code Online (Sandbox Code Playgroud)
我还没有完全明白它的作用.我可以打开输出图像,但它不是数组的正确表示.
如果我改变了一些东西,例如制作一个二维数组,那么图像查看器会告诉我"预期的整数"并且不会向我显示图像.
到现在为止还挺好.因为我在图像之前有数组我创建了一个函数aufrunden来舍入到下一个int数,因为我想创建一个方形图像.
int aufrunden (double h)
{
int i =h;
if (h-i == 0)
{
return i;
}
else
{
i = h+1;
return i;
}
}
Run Code Online (Sandbox Code Playgroud)
此功能用于创建图像.如果图像大于数组提供的信息(这a是数组的长度)
double h;
h= sqrt(a/3.0);
int i = aufrunden(h);
FILE *imageFile;
int height=i,width=i;
Run Code Online (Sandbox Code Playgroud)
现在可能会发生,阵列很a=24长.aufrunden使图像3x3所以它有27个值...意味着它缺少1个像素的值.或者更糟糕的是它只是a=23很长.还创建了一个3x3图像.
什么会fwrite(pix,1,18,imageFile);在这些像素中写入信息?如果剩余值仅为0,那将是最好的.
*编辑没关系,我只会在数组的末尾添加0,直到它填满整个方块...抱歉
如果,看起来,你有 Magick++ 并且乐于使用它,你可以用 C/C++ 编写你的代码,如下所示:
////////////////////////////////////////////////////////////////////////////////
// sample.cpp
// Mark Setchell
//
// ImageMagick Magick++ sample code
//
// Compile with:
// g++ sample.cpp -o sample $(Magick++-config --cppflags --cxxflags --ldflags --libs)
////////////////////////////////////////////////////////////////////////////////
#include <Magick++.h>
#include <iostream>
using namespace std;
using namespace Magick;
int main(int argc,char **argv)
{
unsigned char pix[]={200,200,200, 100,100,100, 0,0,0, 255,0,0, 0,255,0, 0,0,255};
// Initialise ImageMagick library
InitializeMagick(*argv);
// Create Image object and read in from pixel data above
Image image;
image.read(2,3,"RGB",CharPixel,pix);
// Write the image to a file - change extension if you want a GIF or JPEG
image.write("result.png");
}
Run Code Online (Sandbox Code Playgroud)
考虑使用Netpbm格式(pbm,pgm或ppm).
这些图像是非常简单的文本文件,您可以在没有任何特殊库的情 然后使用某些第三方软件(如ImageMagick,GraphicsMagick或pnmtopng)将图像转换为PNG格式.这是一篇描述Netpbm格式的wiki文章.
这是一个简单的PPM图像:
P3 2 3 255
0 0 0 255 255 255
255 0 0 0 255 255
100 100 100 200 200 200
Run Code Online (Sandbox Code Playgroud)
第一行包含"P3"(将其标识为文本-PPM的"幻数"),2(宽度),3(高度),255(最大强度).第二行包含顶行的两个RGB像素.第三行和第四行各包含行2和3的两个RGB像素.
如果您需要更大的强度范围(最大65535),请使用更大的数字以获得最大强度(例如1024).
Mark Setchell编辑超越这一点 - 所以我是一个有罪的派对!
图像看起来像这样(当放大六个像素时):
要转换和放大的ImageMagick命令是这样的:
convert image.ppm -scale 400x result.png
Run Code Online (Sandbox Code Playgroud)
如果ImageMagick有点重量级,或者难以安装,你可以更简单地使用NetPBM工具(从这里)这样(它是一个预编译的二进制文件)
pnmtopng image.ppm > result.png
Run Code Online (Sandbox Code Playgroud)
你离得不远了 - 做得很好!据我所知,你只有几个错误:
如果用二进制编写,你就有P3了你真正需要的地方P6。
您正在int为您的数据使用类型,而您需要unsigned char为 8 位数据使用。
你交换了宽度和高度。
您使用的PGM是用于便携式灰度地图的扩展程序,而您的数据是彩色的,因此您需要使用PPM用于便携式像素地图的扩展程序。
因此,工作代码如下所示:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *imageFile;
int x,y,pixel,height=3,width=2;
imageFile=fopen("image.ppm","wb");
if(imageFile==NULL){
perror("ERROR: Cannot open output file");
exit(EXIT_FAILURE);
}
fprintf(imageFile,"P6\n"); // P6 filetype
fprintf(imageFile,"%d %d\n",width,height); // dimensions
fprintf(imageFile,"255\n"); // Max pixel
unsigned char pix[]={200,200,200, 100,100,100, 0,0,0, 255,0,0, 0,255,0, 0,0,255};
fwrite(pix,1,18,imageFile);
fclose(imageFile);
}
Run Code Online (Sandbox Code Playgroud)
如果你然后运行它,你可以将结果图像转换为一个漂亮的大 PNG
convert image.ppm -scale 400x result.png
Run Code Online (Sandbox Code Playgroud)
如果您随后需要 16 位数据,您可以将255to更改为65535,并将其存储在unsigned short数组中,而不是unsigned char当您来到 时fwrite(),您需要写入双倍的字节数。
下面的代码将采用像素颜色的整数数组作为输入并将其写入.bmp位图文件,或者相反,读取位.bmp图文件并将其图像内容存储为数组int。它只需要<fstream>图书馆。path例如,输入参数可以是C:/path/to/your/image.bmp和 ,data其格式为data[x+y*width]=(red<<16)|(green<<8)|blue;,其中red、green和blue是范围内的整数0-255,像素位置是(x,y)。
#include <string>
#include <fstream>
using namespace std;
typedef unsigned int uint;
int* read_bmp(const string path, uint& width, uint& height) {
ifstream file(path, ios::in|ios::binary);
if(file.fail()) println("\rError: File \""+filename+"\" does not exist!");
uint w=0, h=0;
char header[54];
file.read(header, 54);
for(uint i=0; i<4; i++) {
w |= (header[18+i]&255)<<(8*i);
h |= (header[22+i]&255)<<(8*i);
}
const int pad=(4-(3*w)%4)%4, imgsize=(3*w+pad)*h;
char* img = new char[imgsize];
file.read(img, imgsize);
file.close();
int* data = new int[w*h];
for(uint y=0; y<h; y++) {
for(uint x=0; x<w; x++) {
const int i = 3*x+y*(3*w+pad);
data[x+(h-1-y)*w] = (img[i]&255)|(img[i+1]&255)<<8|(img[i+2]&255)<<16;
}
}
delete[] img;
width = w;
height = h;
return data;
}
void write_bmp(const string path, const uint width, const uint height, const int* const data) {
const int pad=(4-(3*width)%4)%4, filesize=54+(3*width+pad)*height; // horizontal line must be a multiple of 4 bytes long, header is 54 bytes
char header[54] = { 'B','M', 0,0,0,0, 0,0,0,0, 54,0,0,0, 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,24,0 };
for(uint i=0; i<4; i++) {
header[ 2+i] = (char)((filesize>>(8*i))&255);
header[18+i] = (char)((width >>(8*i))&255);
header[22+i] = (char)((height >>(8*i))&255);
}
char* img = new char[filesize];
for(uint i=0; i<54; i++) img[i] = header[i];
for(uint y=0; y<height; y++) {
for(uint x=0; x<width; x++) {
const int color = data[x+(height-1-y)*width];
const int i = 54+3*x+y*(3*width+pad);
img[i ] = (char)( color &255);
img[i+1] = (char)((color>> 8)&255);
img[i+2] = (char)((color>>16)&255);
}
for(uint p=0; p<pad; p++) img[54+(3*width+p)+y*(3*width+pad)] = 0;
}
ofstream file(path, ios::out|ios::binary);
file.write(img, filesize);
file.close();
delete[] img;
}
Run Code Online (Sandbox Code Playgroud)
代码片段的灵感来自/sf/answers/3344994761/
对于.png图像,请使用lodepng.cpp和lodepng.h:
#include <string>
#include <vector>
#include <fstream>
#include "lodepng.h"
using namespace std;
typedef unsigned int uint;
int* read_png(const string path, uint& width, uint& height) {
vector<uchar> img;
lodepng::decode(img, width, height, path, LCT_RGB);
int* data = new int[width*height];
for(uint i=0; i<width*height; i++) {
data[i] = img[3*i]<<16|img[3*i+1]<<8|img[3*i+2];
}
return data;
}
void write_png(const string path, const uint width, const uint height, const int* const data) {
uchar* img = new uchar[3*width*height];
for(uint i=0; i<width*height; i++) {
const int color = data[i];
img[3*i ] = (color>>16)&255;
img[3*i+1] = (color>> 8)&255;
img[3*i+2] = color &255;
}
lodepng::encode(path, img, width, height, LCT_RGB);
delete[] img;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15971 次 |
| 最近记录: |