MyPNG.cpp (pymol-open-source-2.2.0) | : | MyPNG.cpp (pymol-open-source-2.3.0) | ||
---|---|---|---|---|
skipping to change at line 145 | skipping to change at line 145 | |||
*/ | */ | |||
static void write_data_to_buffer(png_structp png_ptr, | static void write_data_to_buffer(png_structp png_ptr, | |||
png_bytep data, | png_bytep data, | |||
png_size_t length) { | png_size_t length) { | |||
#if 0 | #if 0 | |||
auto io_ptr = (std::vector<unsigned char>*) png_get_io_ptr(png_ptr); | auto io_ptr = (std::vector<unsigned char>*) png_get_io_ptr(png_ptr); | |||
io_ptr->insert(io_ptr->end(), data, data + length); | io_ptr->insert(io_ptr->end(), data, data + length); | |||
#endif | #endif | |||
} | } | |||
/* | ||||
* Use with png_set_read_fn instead of png_init_io, allows mixing of | ||||
* Visual Studio versions | ||||
*/ | ||||
static void read_data_from_file( | ||||
png_structp png_ptr, | ||||
png_bytep buffer, | ||||
png_size_t count) { | ||||
auto fp = static_cast<FILE*>(png_get_io_ptr(png_ptr)); | ||||
fread(buffer, 1, count, fp); | ||||
} | ||||
/* | ||||
* Use with png_set_write_fn instead of png_init_io, allows mixing of | ||||
* Visual Studio versions | ||||
*/ | ||||
static void write_data_to_file( | ||||
png_structp png_ptr, | ||||
png_bytep buffer, | ||||
png_size_t count) { | ||||
auto fp = static_cast<FILE*>(png_get_io_ptr(png_ptr)); | ||||
fwrite(buffer, 1, count, fp); | ||||
} | ||||
#endif | #endif | |||
int MyPNGWrite(PyMOLGlobals * G, const char *file_name, const unsigned char *dat | int MyPNGWrite(const char* file_name, const pymol::Image& img, const float dpi, | |||
a_ptr, | const int format, const int quiet, const float screen_gamma, | |||
unsigned int width, unsigned int height, float dpi, int format, i | const float file_gamma, void* io_ptr) | |||
nt quiet, | ||||
void * io_ptr) | ||||
{ | { | |||
const unsigned char* data_ptr = img.bits(); | ||||
int width = img.getWidth(); | ||||
int height = img.getHeight(); | ||||
switch (format) { | switch (format) { | |||
case cMyPNG_FormatPNG: | case cMyPNG_FormatPNG: | |||
{ | { | |||
#ifdef _PYMOL_LIBPNG | #ifdef _PYMOL_LIBPNG | |||
int ok = true; | int ok = true; | |||
FILE *fp = NULL; | FILE *fp = NULL; | |||
png_structp png_ptr; | png_structp png_ptr; | |||
png_infop info_ptr; | png_infop info_ptr; | |||
int bit_depth = 8; | int bit_depth = 8; | |||
int bytes_per_pixel = 4; | int bytes_per_pixel = 4; | |||
skipping to change at line 221 | skipping to change at line 247 | |||
/* If we get here, we had a problem reading the file */ | /* If we get here, we had a problem reading the file */ | |||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | |||
ok = false; | ok = false; | |||
goto cleanup; | goto cleanup; | |||
} | } | |||
if (io_ptr) { | if (io_ptr) { | |||
png_set_write_fn(png_ptr, (void*) io_ptr, write_data_to_buffer, NULL); | png_set_write_fn(png_ptr, (void*) io_ptr, write_data_to_buffer, NULL); | |||
} else { | } else { | |||
/* set up the output control if you are using standard C streams */ | /* set up the output control if you are using standard C streams */ | |||
png_init_io(png_ptr, fp); | png_set_write_fn(png_ptr, (void*) fp, write_data_to_file, NULL); | |||
} | } | |||
/* Set the image information here. Width and height are up to 2^31, | /* Set the image information here. Width and height are up to 2^31, | |||
* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on | * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on | |||
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, | * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, | |||
* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, | * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, | |||
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or | * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or | |||
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST | * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST | |||
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIR ED | * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIR ED | |||
*/ | */ | |||
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_R GB_ALPHA, | png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_R GB_ALPHA, | |||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYP E_BASE); | PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYP E_BASE); | |||
if(dpi > 0.0F) { /* only set resolution if dpi is positive */ | if(dpi > 0.0F) { /* only set resolution if dpi is positive */ | |||
int dots_per_meter = (int) (dpi * 39.3700787); | int dots_per_meter = (int) (dpi * 39.3700787); | |||
png_set_pHYs(png_ptr, info_ptr, dots_per_meter, dots_per_meter, | png_set_pHYs(png_ptr, info_ptr, dots_per_meter, dots_per_meter, | |||
PNG_RESOLUTION_METER); | PNG_RESOLUTION_METER); | |||
} | } | |||
png_set_gamma(png_ptr, SettingGetGlobal_f(G, cSetting_png_screen_gamma), | png_set_gamma(png_ptr, screen_gamma, file_gamma); | |||
SettingGetGlobal_f(G, cSetting_png_file_gamma)); | ||||
/* stamp the image as being created by PyMOL we could consider | /* stamp the image as being created by PyMOL we could consider | |||
* supporting optional annotations as well: PDB codes, canonical | * supporting optional annotations as well: PDB codes, canonical | |||
* smiles, INCHIs, and other common identifiers */ | * smiles, INCHIs, and other common identifiers */ | |||
{ | { | |||
png_text text; | png_text text; | |||
text.compression = PNG_TEXT_COMPRESSION_NONE; | text.compression = PNG_TEXT_COMPRESSION_NONE; | |||
text.key = (png_charp) "Software"; | text.key = (png_charp) "Software"; | |||
text.text = (png_charp) "PyMOL"; | text.text = (png_charp) "PyMOL"; | |||
skipping to change at line 336 | skipping to change at line 361 | |||
fclose(fil); | fclose(fil); | |||
} | } | |||
FreeP(buffer); | FreeP(buffer); | |||
} | } | |||
return 1; | return 1; | |||
break; | break; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
int MyPNGRead(const char *file_name, unsigned char **p_ptr, unsigned int *width_ | std::unique_ptr<pymol::Image> MyPNGRead(const char *file_name) | |||
ptr, | ||||
unsigned int *height_ptr) | ||||
{ | { | |||
std::unique_ptr<pymol::Image> img; | ||||
#ifdef _PYMOL_LIBPNG | #ifdef _PYMOL_LIBPNG | |||
FILE *png_file = NULL; | FILE *png_file = NULL; | |||
png_struct *png_ptr = NULL; | png_struct *png_ptr = NULL; | |||
png_info *info_ptr = NULL; | png_info *info_ptr = NULL; | |||
png_byte buf[8]; | png_byte buf[8]; | |||
png_byte *png_pixels = NULL; | png_byte *png_pixels = NULL; | |||
png_byte **row_pointers = NULL; | png_byte **row_pointers = NULL; | |||
png_byte *pix_ptr = NULL; | png_byte *pix_ptr = NULL; | |||
png_uint_32 row_bytes = 0; | png_uint_32 row_bytes = 0; | |||
png_uint_32 width; | png_uint_32 width; | |||
png_uint_32 height; | png_uint_32 height; | |||
int bit_depth; | int bit_depth; | |||
int color_type; | int color_type; | |||
int row, col; | int row, col; | |||
int ret; | int ret; | |||
int i; | int i; | |||
int ok = true; | int ok = true; | |||
unsigned char *p = NULL; | ||||
double file_gamma; | double file_gamma; | |||
uchar2p data = {NULL, NULL}; | uchar2p data = {NULL, NULL}; | |||
if(!file_name) | if(!file_name) | |||
return 0; | return nullptr; | |||
if(!strncmp(file_name, "data:image/png;base64,", 22)) { | if(!strncmp(file_name, "data:image/png;base64,", 22)) { | |||
const char *base64str = file_name + 22; | const char *base64str = file_name + 22; | |||
data.h = data.c = base64_decode(base64str); | data.h = data.c = base64_decode(base64str); | |||
memcpy(buf, data.c, 8); | memcpy(buf, data.c, 8); | |||
data.c += 8; | data.c += 8; | |||
} else { | } else { | |||
png_file = pymol_fopen(file_name, "rb"); | png_file = pymol_fopen(file_name, "rb"); | |||
if(png_file == NULL) | if(png_file == NULL) | |||
return 0; | return nullptr; | |||
/* read and check signature in PNG file */ | /* read and check signature in PNG file */ | |||
ret = fread(buf, 1, 8, png_file); | ret = fread(buf, 1, 8, png_file); | |||
if(ret != 8) | if(ret != 8) | |||
ok = false; | ok = false; | |||
} | } | |||
if(ok) { | if(ok) { | |||
ret = png_check_sig(buf, 8); | ret = png_check_sig(buf, 8); | |||
if(!ret) | if(!ret) | |||
skipping to change at line 410 | skipping to change at line 433 | |||
if(ok && setjmp(png_jmpbuf(png_ptr))) | if(ok && setjmp(png_jmpbuf(png_ptr))) | |||
ok = false; | ok = false; | |||
if(ok) { | if(ok) { | |||
/* set up the input control for C streams */ | /* set up the input control for C streams */ | |||
if(data.h) { | if(data.h) { | |||
png_set_read_fn(png_ptr, (void*) &data, read_data_from_buffer); | png_set_read_fn(png_ptr, (void*) &data, read_data_from_buffer); | |||
} else { | } else { | |||
png_init_io(png_ptr, png_file); | png_set_read_fn(png_ptr, (void*) png_file, read_data_from_file); | |||
} | } | |||
png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ | png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ | |||
/* read the file information */ | /* read the file information */ | |||
png_read_info(png_ptr, info_ptr); | png_read_info(png_ptr, info_ptr); | |||
/* get size and bit-depth of the PNG-image */ | /* get size and bit-depth of the PNG-image */ | |||
png_get_IHDR(png_ptr, info_ptr, | png_get_IHDR(png_ptr, info_ptr, | |||
&width, &height, &bit_depth, &color_type, NULL, NULL, NULL); | &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); | |||
skipping to change at line 474 | skipping to change at line 497 | |||
for(i = 0; i < ((signed) height); i++) | for(i = 0; i < ((signed) height); i++) | |||
row_pointers[i] = png_pixels + i * row_bytes; | row_pointers[i] = png_pixels + i * row_bytes; | |||
/* now we can go ahead and just read the whole image */ | /* now we can go ahead and just read the whole image */ | |||
png_read_image(png_ptr, row_pointers); | png_read_image(png_ptr, row_pointers); | |||
/* read rest of file, and get additional chunks in info_ptr - REQUIRED */ | /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ | |||
png_read_end(png_ptr, info_ptr); | png_read_end(png_ptr, info_ptr); | |||
} | } | |||
img = pymol::make_unique<pymol::Image>(width, height); | ||||
if(ok) { | if(ok) { | |||
/* now reformat image into PyMOL format */ | auto p = img->bits(); | |||
p = (unsigned char *) mmalloc(4 * width * height); | ||||
if(!p) | ||||
ok = false; | ||||
} | ||||
if(ok) { | ||||
*(p_ptr) = p; | ||||
*(width_ptr) = width; | ||||
*(height_ptr) = height; | ||||
for(row = 0; row < (signed) height; row++) { | for(row = 0; row < (signed) height; row++) { | |||
pix_ptr = row_pointers[(height - 1) - row]; | pix_ptr = row_pointers[(height - 1) - row]; | |||
for(col = 0; col < (signed) width; col++) { | for(col = 0; col < (signed) width; col++) { | |||
*p++ = *pix_ptr++; | *p++ = *pix_ptr++; | |||
*p++ = *pix_ptr++; | *p++ = *pix_ptr++; | |||
*p++ = *pix_ptr++; | *p++ = *pix_ptr++; | |||
*p++ = *pix_ptr++; | *p++ = *pix_ptr++; | |||
} | } | |||
} | } | |||
skipping to change at line 510 | skipping to change at line 525 | |||
free(png_pixels); | free(png_pixels); | |||
if(png_ptr) { | if(png_ptr) { | |||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); | png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); | |||
} | } | |||
if(png_file) | if(png_file) | |||
fclose(png_file); | fclose(png_file); | |||
if(data.h) | if(data.h) | |||
mfree(data.h); | mfree(data.h); | |||
return (ok); | return img; | |||
#else | #else | |||
return (false); | return nullptr; | |||
#endif | #endif | |||
} /* end of source */ | } /* end of source */ | |||
End of changes. 15 change blocks. | ||||
28 lines changed or deleted | 40 lines changed or added |