int simpl_gray_to_image(SimplImage **image, const SimplGrayImage *gray_img, const SimplGrayToColorMethods method) { size_t i, size; int result; if (gray_img && gray_img->image && gray_img->width && gray_img->height) { result = simpl_image(image, gray_img->width, gray_img->height); if (result!=SIMPL_OK) return result; size = gray_img->width * gray_img->height; switch (method) { case GRAY_TO_COLOR_RED: for (i=0; i<size; ++i) { (*image)->image[i].red = gray_img->image[i]; } break; case GRAY_TO_COLOR_GREEN: for (i=0; i<size; ++i) { (*image)->image[i].green = gray_img->image[i]; } break; case GRAY_TO_COLOR_BLUE: for (i=0; i<size; ++i) { (*image)->image[i].blue = gray_img->image[i]; } break; case GRAY_TO_COLOR_ALPHA: simpl_alpha_create(*image); for (i=0; i<size; ++i) { (*image)->alpha[i] = gray_img->image[i]; } break; case GRAY_TO_ALL: default: for (i=0; i<size; ++i) { (*image)->image[i].red = gray_img->image[i]; (*image)->image[i].green = gray_img->image[i]; (*image)->image[i].blue = gray_img->image[i]; } break; } } else return SIMPL_BAD_PARAMS; return SIMPL_OK; }
int simpl_image_copy(SimplImage **dest_img, const SimplImage *src_img) { int result; if (src_img && src_img->image && src_img->width && src_img->height) { if (*dest_img==src_img) return SIMPL_OK; result = simpl_image(dest_img, src_img->width, src_img->height); if (result!=SIMPL_OK) return result; memcpy((*dest_img)->image, src_img->image, src_img->width * src_img->height * sizeof(SimplColorPixel)); if (src_img->alpha) { simpl_alpha_create(*dest_img); memcpy((*dest_img)->alpha, src_img->alpha, src_img->width * src_img->height * sizeof(SimplPixel)); } } else return SIMPL_BAD_PARAMS; return SIMPL_OK; }
int simpl_image_load_png(SimplImage **image, SimplInStream istream) { png_structp png_ptr; png_infop info_ptr; png_byte color_type, bitdepth, *row_data=NULL; png_bytep* row_ptrs=NULL; png_uint_32 i, j, width, height, row_size; SimplColorPixel *iptr; SimplPixel *aptr; int out = SIMPL_INTERNAL; /* Create a read struct. */ if (!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) { return SIMPL_INTERNAL; } /* Create an info struct. */ if (!(info_ptr = png_create_info_struct(png_ptr))) { goto error; } /* Handle libpng errors with a magic setjmp. */ if (setjmp(png_jmpbuf(png_ptr))) { goto error; } /* Set the stream-based data source. */ png_set_read_fn(png_ptr, istream, StreamReadData); /* Read the info chunk. */ png_read_info(png_ptr, info_ptr); /* Get the dimensions and color information. */ width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); bitdepth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); /* If palette, low bit depth gray, transparent w/o alpha, or 16 bit, fix it. */ if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); color_type = png_get_color_type(png_ptr, info_ptr); } else if (color_type == PNG_COLOR_TYPE_GRAY) { if (bitdepth<8) png_set_expand_gray_1_2_4_to_8(png_ptr); bitdepth = 8; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); color_type = png_get_color_type(png_ptr, info_ptr); } png_set_strip_16(png_ptr); /* Either allocate a row, or load the entire image into a buffer. This is * because single row access uses less memory but doesn't work for * interlaced PNGs. */ row_size = png_get_rowbytes(png_ptr, info_ptr); if (png_get_interlace_type(png_ptr, info_ptr)==PNG_INTERLACE_NONE) { row_data = (png_byte *)malloc(sizeof(png_byte) * row_size); if (!row_data) { out = SIMPL_NOMEM; goto error; } } else { row_ptrs = (png_bytep*)calloc(height, sizeof(png_bytep)); if (!row_ptrs) { out = SIMPL_NOMEM; goto error; } for (j=0; j<height; ++j) { row_ptrs[j] = (png_byte *)malloc(sizeof(png_byte) * row_size); if (!row_ptrs[j]) { out = SIMPL_NOMEM; goto error; } } png_read_image(png_ptr, row_ptrs); } /* Allocate an image of the specified size. */ out = simpl_image(image, width, height); if (out != SIMPL_OK) goto error; /* Store the decoded image into our format. */ if (color_type == PNG_COLOR_TYPE_RGB) { for (j=0; j<height; j++) { if (row_ptrs) row_data = row_ptrs[j]; else png_read_row(png_ptr, row_data, NULL); iptr = (*image)->image + j * width; for (i=0; i<3*width; i+=3) { iptr->red = row_data[i]; iptr->green = row_data[i+1]; iptr->blue = row_data[i+2]; iptr++; } } } else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { simpl_alpha_create(*image); for (j=0; j<height; j++) { if (row_ptrs) row_data = row_ptrs[j]; else png_read_row(png_ptr, row_data, NULL); iptr = (*image)->image + j * width; aptr = (*image)->alpha + j * width; for (i=0; i<4*width; i+=4) { iptr->red = row_data[i]; iptr->green = row_data[i+1]; iptr->blue = row_data[i+2]; iptr++; *aptr++ = row_data[i+3]; } } } else if (color_type == PNG_COLOR_TYPE_GRAY) { for (j=0; j<height; j++) { if (row_ptrs) row_data = row_ptrs[j]; else png_read_row(png_ptr, row_data, NULL); iptr = (*image)->image + j * width; for (i=0; i<width; i++) { iptr->red = row_data[i]; iptr->green = row_data[i]; iptr->blue = row_data[i]; iptr++; } } } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { simpl_alpha_create(*image); for (j=0; j<height; j++) { if (row_ptrs) row_data = row_ptrs[j]; else png_read_row(png_ptr, row_data, NULL); iptr = (*image)->image + j * width; aptr = (*image)->alpha + j * width; for (i=0; i<2*width; i+=2) { iptr->red = row_data[i]; iptr->green = row_data[i]; iptr->blue = row_data[i]; iptr++; *aptr++ = row_data[i+1]; } } } else goto error; error: if (row_ptrs) { for (j=0; j<height; ++j) { if (row_ptrs[j]) free((void *)row_ptrs[j]); } free((void *)row_ptrs); } else { if (row_data) free((void *)row_data); } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return out; }