Related
Complete C++/C newbie here. I recompiled gcz2tga (I did not make this code, just found it on the webs) into a debug .exe file using Visual Studio 2019. Everything works well until it gets to "split_images" and then the program spits out this error:
Debug Error!
Program: C:\Users\Harrison\source\repos\gcz2tga\Debug\gcz2tga.exe
abort() has been called
(Press Retry to debug the application)
When I hit Retry, the program closes. The code is set up like this:
/* gcz2tga.c: Slice up a directory full of GCZ (texture) files into TGA files.
*
* Credit goes to afwefwe for reverse-engineering the texture format
* and LZSS compression */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* Assuming x86, usual endian crap is not accounted for */
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned int u32_t;
struct image
{
unsigned int width, height;
u8_t *planes;
};
struct clip
{
short x, y, w, h;
};
static u16_t swab16(u16_t in)
{
/* GC headers are big-endian */
return ((in & 0xFF) << 8) | (in >> 8);
}
static void unpack_gc(struct image *out, u8_t *in, size_t out_sz)
{
unsigned int npixels;
unsigned int i;
unsigned int j;
u16_t *pixels;
u16_t *pheight;
u16_t *pwidth;
u16_t *pmagic;
u16_t pixel;
pmagic = (u16_t *) in;
pheight = (u16_t *) (in + 14);
pwidth = (u16_t *) (in + 12);
if (*pmagic != 0x4347) {
fprintf(stderr, "(FAIL: Invalid header)\n");
exit(EXIT_FAILURE);
}
/* Set up output image struct */
in += 24;
out->width = swab16(*pwidth);
out->height = swab16(*pheight);
out->planes = malloc(out->width * out->height * 4);
/* Clamp W/H (don't know why this is necessary but it is) */
out->width = out->width > 1024 ? 1024 : out->width;
out->height = out->height > 1024 ? 1024 : out->height;
fprintf(stderr, "(%dx%d)", out->width, out->height);
/* Unpack pixels */
pixels = (u16_t *) in;
npixels = out->width * out->height;
if (out_sz > npixels * 4) {
/* Deep image (i.e. 32-bit) */
memcpy(out->planes, pixels, npixels * 4);
} else {
/* Shallow image (i.e. 16-bit) */
for (i = 0, j = 0 ; i < npixels ; i++) {
pixel = pixels[i];
out->planes[j++] = ((pixel ) & 0x1F) << 3; /* B */
out->planes[j++] = ((pixel >> 5) & 0x1F) << 3; /* G */
out->planes[j++] = ((pixel >> 10) ) << 3; /* R */
out->planes[j++] = pixel & 0x8000 ? 0xFF : 0x00; /* A */
}
}
}
static u8_t *expand_lzss(u8_t *lzss, size_t *pout_sz)
{
static u8_t ring[0x1000];
unsigned int ring_pos = 0x0FEE;
unsigned int chunk_offset;
unsigned int chunk_length;
u32_t control_word = 1;
size_t length;
u8_t cmd1;
u8_t cmd2;
u8_t *out;
u8_t *pos;
u8_t *in;
/* Header = 32 bit unpacked file length */
length = *((u32_t *) lzss);
*pout_sz = length;
if (length > 8000000) {
fprintf(stderr, "(FAIL: Unreasonably large expanded size %d)\n",
length);
exit(EXIT_FAILURE);
}
out = malloc(length * 2); /* Seems to overrun */
pos = out;
in = lzss + 4;
while (length > 0) {
if (control_word == 1) {
/* Read a control byte */
control_word = 0x100 | *in++;
}
/* Decode a byte according to the current control byte bit */
if (control_word & 1) {
/* Straight copy */
*pos++ = *in;
ring[ring_pos] = *in++;
ring_pos = (ring_pos + 1) % 0x1000;
length--;
} else {
/* Reference to data in ring buffer */
cmd1 = *in++;
cmd2 = *in++;
chunk_length = (cmd2 & 0x0F) + 3;
chunk_offset = ((cmd2 & 0xF0) << 4) | cmd1;
for ( ; chunk_length > 0 ; chunk_length--) {
/* Copy historical data to output AND current ring pos */
*pos++ = ring[chunk_offset];
ring[ring_pos] = ring[chunk_offset];
/* Update counters */
chunk_offset = (chunk_offset + 1) % 0x1000;
ring_pos = (ring_pos + 1) % 0x1000;
length--;
}
}
/* Get next control bit */
control_word >>= 1;
}
return out;
}
static void readfile(const char *filename, u8_t **data, long *nbytes)
{
FILE *f;
f = fopen(filename, "rb");
if (f == NULL) abort();
fseek(f, 0, SEEK_END);
*nbytes = ftell(f);
fseek(f, 0, SEEK_SET);
*data = malloc(*nbytes);
fread(*data, *nbytes, 1, f);
fclose(f);
}
void put8(FILE *f, unsigned char val)
{
fwrite(&val, 1, 1, f);
}
void put16(FILE *f, unsigned short val)
{
fwrite(&val, 2, 1, f);
}
void split_images(const char *in_dir, const char *out_dir,
struct image *images, int nimages)
{
struct clip *clips;
char filename[512];
long nbytes;
u8_t *data;
char *name;
FILE *f;
int i;
int j;
int k;
/* Read file and get TOC */
sprintf(filename, "%s/system.idx", in_dir);
readfile(filename, &data, &nbytes);
clips = (struct clip *) (data + 0x01BC);
name = (char *) (data + 8 + *((long *) data));
/* Guess how many clips there are with a heuristic */
for (i = 0 ; clips[i].w != 0 && clips[i].h != 0 ; i++) {
sprintf(filename, "%s/%s.tga", out_dir, name);
name += strlen(name) + 3;
f = fopen(filename, "wb");
if (f == NULL) abort();
/* Locate the correct source image */
j = 0;
while (clips[i].y > images[j].height) {
clips[i].y -= images[j].height;
j++;
}
/* Write header */
put8(f, 0); put8(f, 0); put8(f, 2);
put16(f, 0); put16(f, 0); put8(f, 0);
put16(f, 0); put16(f, 0); put16(f, clips[i].w); put16(f, clips[i].h);
put8(f, 32); put8(f, 32);
/* Write scanlines */
for (k = 0 ; k < clips[i].h ; k++) {
if (clips[i].y == images[j].height) {
clips[i].y = 0;
j++;
}
fwrite(images[j].planes + ((images[j].width * clips[i].y) +
clips[i].x) * 4, clips[i].w, 4, f);
clips[i].y++;
}
/* Close output file */
fclose(f);
}
/* Cleanup */
free(data);
}
int main(int argc, char **argv)
{
char *in_dir;
char *out_dir;
struct image images[32];
char filename[256];
unsigned int i;
long filesize;
u8_t *lzss, *gc;
size_t out_sz;
FILE *f;
/* Usage */
if (argc != 3) {
fprintf(stderr, "Usage: %s [indir] [outdir]\n", argv[0]);
return EXIT_FAILURE;
}
/* Setup */
memset(images, 0, sizeof(images));
in_dir = argv[1];
out_dir = argv[2];
for (i = 0 ; i < 32 ; i++) {
/* Open 0.gcz, 1.gcz etc ... */
sprintf(filename, "%s/%d.gcz", in_dir, i);
f = fopen(filename, "rb");
if (f == NULL) break;
/* Read entire file */
fseek(f, 0, SEEK_END);
filesize = ftell(f);
fseek(f, 0, SEEK_SET);
fprintf(stderr, "%s: fread", filename);
lzss = malloc(filesize);
fread(lzss, filesize, 1, f);
fclose(f);
/* Decompress */
fprintf(stderr, "(OK) expand_lzss");
gc = expand_lzss(lzss, &out_sz);
free(lzss);
/* Unpack GC to 32-bit RGBA */
fprintf(stderr, "(OK) unpack_gc");
unpack_gc(&images[i], gc, out_sz);
free(gc);
fprintf(stderr, "(OK)\n");
}
/* Sanity check */
if (i == 0) {
fprintf(stderr, "No GCZ files found\n");
exit(EXIT_FAILURE);
}
/* Emit pile of TGAs */
fprintf(stderr, "split_images");
split_images(in_dir, out_dir, images, i);
fprintf(stderr, "(OK)\n\n");
return 0;
}
What is wrong with the code that could be causing this? The code is unaltered save for #define _CRT_SECURE_NO_WARNINGS being added to the code before the #include headers and having the program compiled as C.
I'm trying to get a grasp of basic features in libpng. To do this, I've used this snippet and adapted to my own example.
int x, y;
png_byte color_type = PNG_COLOR_TYPE_RGBA;
png_byte bit_depth = 16;
png_structp png_ptr;
png_infop info_ptr;
auto create_image(const int height, const int width) {
png_byte **rows = new png_byte *[height];
for (auto i = 0; i < height; i++)
rows[i] = new png_byte[width * 4];
return rows;
}
auto modify_image(const int height, const int width, png_byte **rows) {
for (auto i = 0; i < height; i++) {
for (auto j = 0; j < width; j++) {
// Red channel
rows[i][j * 4 + 0] = (j * 127.) / width;
// Blue channel
rows[i][j * 4 + 2] = (i * 127.) / height;
// Alpha channel
rows[i][j * 4 + 3] = 127;
}
}
}
void write(const std::string& filename, const int height, const int width, png_byte** rows)
{
/* create file */
FILE *fp = fopen(filename.c_str(), "wb");
if (!fp)
abort_("[write_png_file] File %s could not be opened for writing", filename);
/* initialize stuff */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
abort_("[write_png_file] png_create_write_struct failed");
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
abort_("[write_png_file] png_create_info_struct failed");
if (setjmp(png_jmpbuf(png_ptr)))
abort_("[write_png_file] Error during init_io");
png_init_io(png_ptr, fp);
/* write header */
if (setjmp(png_jmpbuf(png_ptr)))
abort_("[write_png_file] Error during writing header");
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
/* write bytes */
if (setjmp(png_jmpbuf(png_ptr)))
abort_("[write_png_file] Error during writing bytes");
png_write_image(png_ptr, rows);
/* end write */
if (setjmp(png_jmpbuf(png_ptr)))
abort_("[write_png_file] Error during end of write");
png_write_end(png_ptr, NULL);
fclose(fp);
}
Though, when I run my code:
void render(const int height, const int width, const std::string &filename) {
png_byte **rows = create_image(height, width);
modify_image(height, width, rows);
write(filename, height, width, rows);
}
The problem is... I don't get the expected result at all. While I was expecting a square image with some kind of gradient I get... two rectangular rectangles.
Also, I've noticed that these two rectangles are stretched: while trying to render a circle, I've found that the circle was distorted and doubling its width makes it an actual circle...
Finally, I've seen that on the second rectangle, the last row seems to be random data (which is not the case on the first rectangle).
Please suggest if you have any ideas.
You create image with 16 bit depth yet use 1 byte per channel. Output image consists of odd / even rows of your original image being put on the same row. Basically each line of the right rectangle is caused by a buffer overrun. You need to allocate buffers that are twice as big, that is width * 4 * 2 and fill higher and lower bytes of each channel separately.
I am trying to compile a project using make command.
I have several occured errors about namespace std::.
I am using Ubuntu and I think I've installed all I need to compile C++ language.
Here's the code:
#include "texture.hpp"
#include "texturefetch.hpp"
#include <png.h>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <assert.h>
#include <string>
Texture::~Texture(){
delete[] mPixels;
for (int i=1; i<mlodmax+1; ++i)
delete[] mMipMapLevels[i];
delete[] mMipMapLevels;
}
bool Texture::getclamp() const
{
return clamp;
}
void Texture::setclamp(bool value)
{
clamp = value;
}
int Texture::load(std::string filename){
FILE *fp;
png_byte magic[8];
/* open image file */
fp = std::fopen (filename.c_str(), "rb");
if (!fp) {
fprintf (stderr, "error: couldn't open \"%s\"!\n", filename.c_str());
return 0;
}
/* read magic number */
fread (magic, 1, sizeof (magic), fp);
/* check for valid magic number */
if (!png_check_sig (magic, sizeof (magic))) {
fprintf (stderr, "error: \"%s\" is not a valid PNG image!\n", filename.c_str());
fclose (fp);
return 0;
}
/* create a png read struct */
png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose (fp);
return 0;
}
/* create a png info struct */
png_infop info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr) {
fclose (fp);
png_destroy_read_struct (&png_ptr, NULL, NULL);
return 0;
}
/* initialize the setjmp for returning properly after a libpng
error occured */
if (setjmp (png_jmpbuf (png_ptr))) {
fclose (fp);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return 0;
}
/* setup libpng for using standard C fread() function
with our FILE pointer */
png_init_io (png_ptr, fp);
/* tell libpng that we have already read the magic number */
png_set_sig_bytes (png_ptr, sizeof (magic));
/* read png info */
png_read_info (png_ptr, info_ptr);
int bit_depth, color_type;
/* get some usefull information from header */
bit_depth = png_get_bit_depth (png_ptr, info_ptr);
color_type = png_get_color_type (png_ptr, info_ptr);
/* convert index color images to RGB images */
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb (png_ptr);
/* convert 1-2-4 bits grayscale images to 8 bits
grayscale. */
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png_ptr);
if (bit_depth == 16)
png_set_strip_16 (png_ptr);
else if (bit_depth < 8)
png_set_packing (png_ptr);
/* update info structure to apply transformations */
png_read_update_info (png_ptr, info_ptr);
/* retrieve updated information */
png_get_IHDR (png_ptr, info_ptr,
(png_uint_32*)(&mWidth),
(png_uint_32*)(&mHeight),
&bit_depth, &color_type,
NULL, NULL, NULL);
switch (color_type) {
case PNG_COLOR_TYPE_GRAY:
mPixelFormat = 1;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
mPixelFormat = 2;
break;
case PNG_COLOR_TYPE_RGB:
mPixelFormat = 3;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
mPixelFormat = 4;
break;
default:
/* Badness */
break;
}
/* we can now allocate memory for storing pixel data */
mPixels = new unsigned char[mWidth * mHeight * mPixelFormat];
png_bytep *row_pointers;
/* setup a pointer array. Each one points at the begening of a row. */
row_pointers = new png_bytep[mHeight];
for (int i = 0; i < mHeight; ++i) {
row_pointers[i] = (png_bytep)(mPixels +
((mHeight - (i + 1)) * mWidth * mPixelFormat));
}
/* read pixel data using row pointers */
png_read_image (png_ptr, row_pointers);
/* finish decompression and release memory */
png_read_end (png_ptr, NULL);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
fclose (fp);
/* we don't need row pointers anymore */
delete[] row_pointers;
return 1;
}
Texture::Texture(std::string filename) : mPixels(NULL), mMipMapLevels(NULL), hasmipmap(false), mSu(1.f), mSv(1.f), clamp(false){
if (!load(filename)) {
std::cerr << "Erreur : impossible de lire le fichier " << filename << std::endl;
} else {
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
}
}
bool Texture::prefilter(){
hasmipmap = buildmipmaps();
return hasmipmap;
}
bool Texture::buildmipmaps(){
mMipMapLevels = new unsigned char*[mlodmax+1];
mMipMapLevels[0] = mPixels;
for (int i=1;i<mlodmax+1; ++i)
mMipMapLevels[i]=NULL;
// Call of the student function
return prefilterTexture(mMipMapLevels, mWidth, mHeight, mPixelFormat, mlodmax+1);
}
void Texture::setScale(float su, float sv){
mSu = 1.f/su;
mSv = 1.f/sv;
}
void Texture::getPixel(float u, float v, float lod, Color &color){
if (clamp){
u = (u>0) ? ((u<1) ? u : 1) : 0;
v = (v>0) ? ((v<1) ? v : 1) : 0;
}
u = mSu*u;
v = mSv*v;
float scaledU = u * (mWidth - 1);
float scaledV = v * (mHeight - 1);
// color = Color(u,v,0);
// return;
int s = ((int)scaledU) % mWidth;
int t = ((int)scaledV) % mHeight;
float ds = scaledU - std::floor(scaledU);
float dt = scaledV - std::floor(scaledV);
if (s<0){
s = s+mWidth;
}
if (t<0){
t = t+mHeight;
}
// Nearest
// color = interpolate(mPixels, mWidth, mHeight, s,t, 0.f,0.f);
// return;
// Linear
// color = interpolate(mPixels, mWidth, mHeight, s,t, ds, dt);
// return;
/* Filtrage */
lod = std::min(lod-1, (float)mlodmax);
if (lod > 0) {
// color = Color(0, std::floor(lod), 0);
// return;
int baselod = (int)std::floor(lod);
int pix = (int)(std::pow(2.f,baselod)); // bigger inferior mipmap level
if (hasmipmap){
// Sous-echantillonnage --> filtrage mip-map
Color color1 = integrateMipMap(baselod, ((float)s + ds)/pix, ((float)t + dt)/pix, mWidth/pix, mHeight/pix);
if (baselod < mlodmax){
pix = std::pow(2.f,baselod+1); // smaller superior mipmap level
Color color2 = integrateMipMap(baselod+1, ((float)s + ds)/pix, ((float)t + dt)/pix, mWidth/pix, mHeight/pix);
float dm = lod - std::floor(lod);
color = color1 * (1-dm) + color2 * dm;
} else {
color = color1;
}
} else {
int cs = pix * (s/pix);
int ct = pix * (t/pix);
Color color1 = integrateExplicit(mMipMapLevels[0], mWidth, mHeight, mPixelFormat, cs, ct, pix, pix);
if (baselod < mlodmax){
pix = std::pow(2.f,baselod+1); // smaller superior mipmap level
cs = pix * (s/pix);
ct = pix * (t/pix);
Color color2 = integrateExplicit(mMipMapLevels[0], mWidth, mHeight, mPixelFormat, cs, ct, pix, pix);
float dm = lod - std::floor(lod);
color = color1 * (1-dm) + color2 * dm;
} else {
color = color1;
}
}
} else {
// color = Color(1/*fabsf(lod)*/, 0, 0);
// return;
color = interpolate(mPixels, mWidth, mHeight, s,t, ds,dt);
}
}
Color Texture::integrateMipMap(int level, float s, float t, int w, int h){
Color color(0.f, 0.f, 0.f);
color = interpolate(mMipMapLevels[level], w, h, (int)s, (int)t, s-std::floor(s), t-std::floor(t));
return color;
}
Color Texture::integrateExplicit(unsigned char *pixels, int imageWidth, int imageHeight, int pixelFormat, float s, float t, int w, int h){
#if 0
Color color(0.f, 0.f, 0.f);
for (int i=0; i<h; i++)
for (int j=0; j<w; j++) {
int k = ((int)(t+i)) % imageHeight;
int l = ((int)(s+j)) % imageWidth;
int linPos = (k*imageWidth + l)*(pixelFormat);
Color centerColor(((float) pixels[linPos])/255.0, ((float) pixels[linPos+1])/255.0, ((float) pixels[linPos+2])/255.0);
color = color + centerColor;
}
color = color * (1.f/(w*h));
return color;
#endif
// Call of the student function
return integrateTexture(pixels, imageWidth, imageHeight, pixelFormat, s, t, w, h);
}
Color Texture::interpolate(unsigned char *pixels, int w, int h, int s, int t, float ds, float dt){
#if 0
Color color;
// Sur échantillonnage --> interpolation
// nearest texel
int linPos = (t*w + s)*(mPixelFormat);
Color centerColor(((float) pixels[linPos])/255.0, ((float) pixels[linPos+1])/255.0, ((float) pixels[linPos+2])/255.0);
Color rightColor;
int r = std::min(s+1, w-1);
int posds = (t*w + r)*(mPixelFormat);
rightColor = Color(
((float) pixels[posds])/255.0,
((float) pixels[posds+1])/255.0,
((float) pixels[posds+2])/255.0
);
Color upColor;
int p = std::min(t+1, h-1);
int posdt = (p*w + s)*(mPixelFormat);
upColor = Color (
((float) pixels[posdt])/255.0,
((float) pixels[posdt+1])/255.0,
((float) pixels[posdt+2])/255.0
);
Color upRightColor;
int posdtds = (p*w + r)*(mPixelFormat);
upRightColor = Color (
((float) pixels[posdtds])/255.0,
((float) pixels[posdtds+1])/255.0,
((float) pixels[posdtds+2])/255.0
);
rightColor = centerColor*(1-ds) + rightColor*ds;
upColor = upColor*(1-ds) + upRightColor*ds;
color = rightColor*(1-dt) + upColor*dt;
return color;
#endif
// Call of the student function
return interpolateTexture(pixels, w, h, mPixelFormat, (float)s+ds, (float)t+dt);
}
And here's errors in terminal:
In file included from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:0:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp: In member function ‘float Texture::computeMipmapLevel(const Vector3D&, const Vector3D&)’:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:55:16: error: ‘log2’ is not a member of ‘std’
return std::log2(std::max(dTdx.norm()*width()*mSu, dTdy.norm()*height()*mSv));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:55:16: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp: In constructor ‘Texture::Texture(std::string)’:
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:44: error: ‘log2’ is not a member of ‘std’
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:44: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:63: error: ‘log2’ is not a member of ‘std’
mlodmax = (int)std::floor(std::min(std::log2(mWidth), std::log2(mHeight)));
^
/home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:162:63: note: suggested alternative:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/vector3d.hpp:3,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.hpp:4,
from /home/celine/OIM-LancerDeRayons-2014/coreraytracer/texture.cpp:1:
/usr/include/x86_64-linux-gnu/bits/math-finite.h:344:15: note: ‘log2’
extern double __REDIRECT_NTH (log2, (double), __log2_finite);
I took a look on internet and I tried to include and but it's still not working...
Thanks!
log2 is a C99 function. It's not in C++98, and therefore not in the std namespace. Either compile in C++11 mode (C++11 is aligned with C99):
// g++ -std=c++11
#include <cmath>
#include <iostream>
int main()
{
std::cout << std::log2(3) << std::endl;
}
... or get the function from the C header, without the namespace:
// g++ -std=c++98
#include <iostream>
#include <math.h>
int main()
{
std::cout << log2(3) << std::endl;
}
How to convert bmp to png properly? I was using this code:
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_DEPRECATE
#include <png.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
void GetDesktopResolution(int& horizontal, int& vertical)
{
RECT desktop;
// Get a handle to the desktop window
const HWND hDesktop = GetDesktopWindow();
// Get the size of screen to the variable desktop
GetWindowRect(hDesktop, &desktop);
// The top left corner will have coordinates (0,0)
// and the bottom right corner will have coordinates
// (horizontal, vertical)
horizontal = desktop.right;
vertical = desktop.bottom;
}
typedef struct _RGBPixel {
uint8_t blue;
uint8_t green;
uint8_t red;
} RGBPixel;
/* Structure for containing decompressed bitmaps. */
typedef struct _RGBBitmap {
RGBPixel *pixels;
size_t width;
size_t height;
size_t bytewidth;
uint8_t bytes_per_pixel;
} RGBBitmap;
/* Returns pixel of bitmap at given point. */
#define RGBPixelAtPoint(image, x, y) \
*(((image)->pixels) + (((image)->bytewidth * (y)) \
+ ((x) * (image)->bytes_per_pixel)))
/* Attempts to save PNG to file; returns 0 on success, non-zero on error. */
int save_png_to_file(RGBBitmap *bitmap, const char *path)
{
FILE *fp = fopen(path, "wb");
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_uint_32 bytes_per_row;
png_byte **row_pointers = NULL;
if (fp == NULL) return -1;
/* Initialize the write struct. */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return -1;
}
/* Initialize the info struct. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
fclose(fp);
return -1;
}
/* Set up error handling. */
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return -1;
}
/* Set image attributes. */
png_set_IHDR(png_ptr,
info_ptr,
bitmap->width,
bitmap->height,
8,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
bytes_per_row = bitmap->width * bitmap->bytes_per_pixel;
png_malloc(png_ptr, bitmap->height * sizeof(png_byte *));
for (y = 0; y < bitmap->height; ++y) {
uint8_t *row = (uint8_t *)png_malloc(png_ptr, sizeof(uint8_t)* bitmap->bytes_per_pixel);
row_pointers[y] = (png_byte *)row; /************* MARKED LINE ***************/
for (x = 0; x < bitmap->width; ++x) {
RGBPixel color = RGBPixelAtPoint(bitmap, x, y);
*row++ = color.red;
*row++ = color.green;
*row++ = color.blue;
}
}
/* Actually write the image data. */
png_init_io(png_ptr, fp);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
/* Cleanup. */
for (y = 0; y < bitmap->height; y++) {
png_free(png_ptr, row_pointers[y]);
}
png_free(png_ptr, row_pointers);
/* Finish writing. */
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return 0;
}
int main()
{
RGBBitmap rgbbitmap;
int w, h;
GetDesktopResolution(w, h);
rgbbitmap.height = h;
rgbbitmap.width = w;
rgbbitmap.bytes_per_pixel = 1;
rgbbitmap.bytewidth = w / 100;
RGBPixel rgbpixel;
rgbpixel.blue = 100;
rgbpixel.green = 100;
rgbpixel.red = 100;
rgbbitmap.pixels = &rgbpixel;
save_png_to_file(&rgbbitmap, "abc.bmp");
return 0;
}
But at runtime, I'm getting this error on the marked line :
Unhandled exception at 0x01258F04 in ProjectName.exe: 0xC0000005: Access violation writing location 0x00000000.
I've searched in the net, I've found this interesting small code, but I wasn't able to found its mother lib. And, I think that using libpng gives you more control on your output image.
How do I fix this issue? Or, maybe it's a wrong way to convert? If so, how may I do that?
You never allocate memory for row_pointers, so it's NULL when you do row_pointers[y] = (png_byte *)row;.
I have use libpng to generate png file. for RGB png, there is no problem. but I want to give the png a transparent property.
I reference some code, and add the places where use * to flaged
*row++ = 230;
*PNG_COLOR_TYPE_RGBA,*
to make it have transparent property,
the code is run sucessfully, but I did't see the transparent effect.
can anyone familiar with libpng or png operation help me?
In this code,
where the pixel_t,& bitmap_t is some data with rgb data.
/* A colored pixel. */
typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} pixel_t;
/* A picture. */
typedef struct {
pixel_t *pixels;
size_t width;
size_t height;
} bitmap_t;
static int save_png_to_file (bitmap_t *bitmap, const char *path)
{
FILE * fp;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_byte ** row_pointers = NULL;
/* "status" contains the return value of this function. At first
it is set to a value which means 'failure'. When the routine
has finished its work, it is set to a value which means
'success'. */
int status = -1;
/* The following number is set by trial and error only. I cannot
see where it it is documented in the libpng manual.
*/
int pixel_size = 3;
int depth = 8;
fp = fopen (path, "wb");
if (! fp) {
goto fopen_failed;
}
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
goto png_create_write_struct_failed;
}
info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) {
goto png_create_info_struct_failed;
}
// png_set_invert_alpha(png_ptr);
/* Set up error handling. */
if (setjmp (png_jmpbuf (png_ptr))) {
goto png_failure;
}
/* Set image attributes. */
png_set_IHDR (png_ptr,
info_ptr,
bitmap->width,
bitmap->height,
depth,
*PNG_COLOR_TYPE_RGBA,*
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
//(png_byte **) added by li
row_pointers = (png_byte **)png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
for (y = 0; y < bitmap->height; ++y) {
//png_byte * added by li
// png_byte *row = (png_byte *)
// png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
png_byte *row = (png_byte *)
png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * 4);
row_pointers[y] = row;
for (x = 0; x < bitmap->width; ++x) {
pixel_t * pixel = pixel_at (bitmap, x, y);
*row++ = pixel->red;
*row++ = pixel->green;
*row++ = pixel->blue;
**row++ = 230;*
}
}
/* Write the image data to "fp". */
png_init_io (png_ptr, fp);
png_set_rows (png_ptr, info_ptr, row_pointers);
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
/* The routine has successfully written the file, so we set
"status" to a value which indicates success. */
status = 0;
for (y = 0; y < bitmap->height; y++) {
png_free (png_ptr, row_pointers[y]);
}
png_free (png_ptr, row_pointers);
png_failure:
png_create_info_struct_failed:
png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
fclose (fp);
fopen_failed:
return status;
}
A truecolor PNG image with alpha , with bitdepth=8, stores the transparency as an extra channel, in RGBA order, in the range 0-255 (0=fully transparent; 255=fully opaque).
What you are doing looks correct to me. Only that a value of 230 means "almost opaque", it might be difficult to detect visually the trasnparency. Try with other values.
BTW, bear in mind that there are other ways to add transparency to a PNG image, see my answer here.
Since this question seems to be the top answer for 'libpng add transparency', I'm adding a compile ready source to this answer
// gcc -g -Wall -o png2 png2.c -lpng
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#define uint8_t unsigned char
typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} pixel_t;
typedef struct {
pixel_t *pixels;
size_t width;
size_t height;
} bitmap_t;
pixel_t *pixel_at(bitmap_t *bitmap, int x, int y)
{return &bitmap->pixels[(bitmap->width * y) + x];}
static int save_png_to_file (bitmap_t *bitmap, const char *path)
{
FILE * fp;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_byte ** row_pointers = NULL;
pixel_t *pixel;
int status = -1;
int depth = 8;
if((fp = fopen(path, "wb")) == NULL)
goto fopen_failed;
if((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
goto png_create_write_struct_failed;
if((info_ptr = png_create_info_struct (png_ptr)) == NULL)
goto png_create_info_struct_failed;
if(setjmp (png_jmpbuf (png_ptr)))
goto png_failure;
png_set_IHDR (png_ptr,
info_ptr,
bitmap->width,
bitmap->height,
depth,
PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
row_pointers = (png_byte **)png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
for(y = 0; y < bitmap->height; y++)
{
png_byte *row = (png_byte *)
png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * 4);
row_pointers[y] = row;
for (x = 0; x < bitmap->width; ++x)
{
pixel = pixel_at (bitmap, x, y);
*row++ = pixel->red;
*row++ = pixel->green;
*row++ = pixel->blue;
*row++ = x; // 0 - completely transparent 255 - completely opaque
}
}
png_init_io (png_ptr, fp);
png_set_rows (png_ptr, info_ptr, row_pointers);
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
status = 0;
for(y = 0; y < bitmap->height; y++)
png_free (png_ptr, row_pointers[y]);
png_free (png_ptr, row_pointers);
png_failure:
png_create_info_struct_failed:
png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
fclose (fp);
fopen_failed:
return status;
}
int main(void)
{
bitmap_t pic;
unsigned char pixels[255*255*3];
int t;
pic.width = 255;
pic.height = 255;
for(t=0; t<255 * 255 * 3; t=t+3) // Just a red square
{
pixels[t+0] = 255;
pixels[t+1] = 0;
pixels[t+2] = 0;
}
pic.pixels = (pixel_t *) &pixels;
save_png_to_file(&pic, "test.png");
return 0;
}