static int test_save_PNG(GP_PixelType pixel_type) { GP_Context *ctx; int ret; ctx = GP_ContextAlloc(100, 100, pixel_type); if (ctx == NULL) { tst_msg("Failed to allocate context"); return TST_UNTESTED; } errno = 0; ret = GP_SavePNG(ctx, "/dev/null", NULL); if (ret == 0) { tst_msg("Saved successfully"); GP_ContextFree(ctx); return TST_SUCCESS; } switch (errno) { case ENOSYS: tst_msg("Not Implemented"); GP_ContextFree(ctx); return TST_SKIPPED; default: tst_msg("Failed and errno is not ENOSYS (%i)", errno); GP_ContextFree(ctx); return TST_FAILED; } }
static int bench_circle(GP_PixelType type) { GP_Context *img = GP_ContextAlloc(800, 600, type); if (img == NULL) { tst_err("Malloc failed"); return TST_UNTESTED; } unsigned int i; for (i = 0; i < 100000; i++) { GP_Circle(img, img->w/2, img->h/2, i % 1000, i%0xff); } return TST_SUCCESS; }
static int bench_line(GP_PixelType type) { GP_Context *img = GP_ContextAlloc(800, 600, type); if (img == NULL) { tst_err("Malloc failed"); return TST_UNTESTED; } unsigned int i; for (i = 0; i < 100000; i++) { GP_Line(img, 0 + i % 100, 0 - i % 100, 800 - i%200, 600 + i%200, i % 0xff); } return TST_SUCCESS; }
GP_Context *GP_FilterGaussianBlurExAlloc(const GP_Context *src, GP_Coord x_src, GP_Coord y_src, GP_Size w_src, GP_Size h_src, float sigma_x, float sigma_y, GP_ProgressCallback *callback) { GP_Context *dst = GP_ContextAlloc(w_src, h_src, src->pixel_type); if (dst == NULL) return NULL; if (GP_FilterGaussianBlur_Raw(src, x_src, y_src, w_src, h_src, dst, 0, 0, sigma_x, sigma_y, callback)) { GP_ContextFree(dst); return NULL; } return dst; }
static int save_load(enum fmt fmt, GP_Size w, GP_Size h) { GP_Context *img, *res; img = GP_ContextAlloc(w, h, GP_PIXEL_RGB888); if (img == NULL) { tst_warn("GP_ContextAlloc failed"); return TST_UNTESTED; } int ret = save_img(fmt, img, "test"); if (ret) { if (errno == ENOSYS) { tst_msg("Save %s: ENOSYS", strfmt(fmt)); return TST_SKIPPED; } tst_msg("Failed to save %s: %s", strfmt(fmt), strerror(errno)); return TST_FAILED; } res = load(fmt, "test"); if (res == NULL) { tst_msg("Failed to load %s: %s", strfmt(fmt), strerror(errno)); return TST_FAILED; } GP_ContextFree(img); GP_ContextFree(res); return TST_SUCCESS; }
static int test_circle(const struct testcase *t) { GP_Context *c; int err; c = GP_ContextAlloc(t->w, t->h, GP_PIXEL_G8); if (c == NULL) { tst_err("Failed to allocate context"); return TST_UNTESTED; } /* zero the pixels buffer */ memset(c->pixels, 0, c->w * c->h); GP_FillCircle(c, t->x, t->y, t->r, 1); err = compare_buffers(t->pixmap, c); if (err) return TST_FAILED; return TST_SUCCESS; }
int GP_ReadJP2Ex(GP_IO *io, GP_Context **rimg, GP_DataStorage *storage, GP_ProgressCallback *callback) { opj_dparameters_t params; opj_codec_t *codec; opj_stream_t *stream; opj_image_t *img; GP_PixelType pixel_type; GP_Context *res = NULL; unsigned int i, x, y; int err = 0, ret = 1; opj_set_default_decoder_parameters(¶ms); codec = opj_create_decompress(OPJ_CODEC_JP2); if (!codec) { GP_DEBUG(1, "opj_create_decompress failed"); err = ENOMEM; goto err0; } opj_set_error_handler(codec, jp2_err_callback, NULL); opj_set_warning_handler(codec, jp2_warn_callback, NULL); opj_set_info_handler(codec, jp2_info_callback, callback); if (!opj_setup_decoder(codec, ¶ms)) { GP_DEBUG(1, "opj_setup_decoder failed"); err = ENOMEM; goto err1; } stream = opj_stream_default_create(OPJ_TRUE); if (!stream) { GP_DEBUG(1, "opj_stream_create_default_file_stream faled"); err = ENOMEM; goto err1; } //TODO: Do we need seek and skip? opj_stream_set_read_function(stream, jp2_io_read); opj_stream_set_user_data(stream, io); if (!opj_read_header(stream, codec, &img)) { GP_DEBUG(1, "opj_read_header failed"); err = EINVAL; goto err2; } if (storage) fill_metadata(img, storage); GP_DEBUG(1, "Have image %ux%u-%ux%u colorspace=%s numcomps=%u", img->x0, img->y0, img->x1, img->y1, color_space_name(img->color_space), img->numcomps); if (!rimg) return 0; /* * Try to match the image information into pixel type. * * Unfortunately the images I had have color_space set * to unspecified yet they were RGB888. */ for (i = 0; i < img->numcomps; i++) { opj_image_comp_t *comp = &img->comps[i]; GP_DEBUG(2, "Component %u %ux%u bpp=%u", i, comp->w, comp->h, comp->prec); if (comp->w != img->comps[0].w || comp->h != img->comps[0].h) { GP_DEBUG(1, "Component %u has different size", 1); err = ENOSYS; goto err3; } if (comp->prec != 8) { GP_DEBUG(1, "Component %u has different bpp", 1); err = ENOSYS; goto err3; } } switch (img->color_space) { case OPJ_CLRSPC_UNSPECIFIED: if (img->numcomps != 3) { GP_DEBUG(1, "Unexpected number of components"); err = ENOSYS; goto err3; } pixel_type = GP_PIXEL_RGB888; break; default: GP_DEBUG(1, "Unsupported colorspace"); err = ENOSYS; goto err3; } GP_ProgressCallbackReport(callback, 0, 100, 100); if (!opj_decode(codec, stream, img)) { GP_DEBUG(1, "opj_decode failed"); err = EINVAL; goto err3; } res = GP_ContextAlloc(img->comps[0].w, img->comps[0].h, pixel_type); if (!res) { GP_DEBUG(1, "Malloc failed :("); err = ENOMEM; goto err3; } for (y = 0; y < res->h; y++) { for (x = 0; x < res->w; x++) { i = y * res->w + x; GP_Pixel p = img->comps[0].data[i] << 16| img->comps[1].data[i] << 8 | img->comps[2].data[i]; GP_PutPixel_Raw_24BPP(res, x, y, p); } } GP_ProgressCallbackDone(callback); *rimg = res; ret = 0; err3: opj_image_destroy(img); err2: opj_stream_destroy(stream); err1: opj_destroy_codec(codec); err0: if (err) errno = err; return ret; }
int GP_ReadJPGEx(GP_IO *io, GP_Context **img, GP_DataStorage *storage, GP_ProgressCallback *callback) { struct jpeg_decompress_struct cinfo; struct my_source_mgr src; struct my_jpg_err my_err; GP_Context *ret = NULL; uint8_t buf[1024]; int err; cinfo.err = jpeg_std_error(&my_err.error_mgr); my_err.error_mgr.error_exit = my_error_exit; if (setjmp(my_err.setjmp_buf)) { err = EIO; goto err2; } jpeg_create_decompress(&cinfo); init_source_mgr(&src, io, buf, sizeof(buf)); cinfo.src = (void*)&src; if (storage) save_jpg_markers(&cinfo); jpeg_read_header(&cinfo, TRUE); GP_DEBUG(1, "Have %s JPEG size %ux%u %i channels", get_colorspace(cinfo.jpeg_color_space), cinfo.image_width, cinfo.image_height, cinfo.num_components); //TODO: Propagate failure? if (storage) read_jpg_metadata(&cinfo, storage); if (!img) goto exit; GP_Pixel pixel_type; switch (cinfo.out_color_space) { case JCS_GRAYSCALE: pixel_type = GP_PIXEL_G8; break; case JCS_RGB: pixel_type = GP_PIXEL_BGR888; break; case JCS_CMYK: pixel_type = GP_PIXEL_CMYK8888; break; default: pixel_type = GP_PIXEL_UNKNOWN; } if (pixel_type == GP_PIXEL_UNKNOWN) { GP_DEBUG(1, "Can't handle %s JPEG output format", get_colorspace(cinfo.out_color_space)); err = ENOSYS; goto err1; } ret = GP_ContextAlloc(cinfo.image_width, cinfo.image_height, pixel_type); if (ret == NULL) { GP_DEBUG(1, "Malloc failed :("); err = ENOMEM; goto err1; } jpeg_start_decompress(&cinfo); switch (pixel_type) { case GP_PIXEL_BGR888: case GP_PIXEL_G8: err = load(&cinfo, ret, callback); break; case GP_PIXEL_CMYK8888: err = load_cmyk(&cinfo, ret, callback); break; default: err = EINVAL; } if (err) goto err2; jpeg_finish_decompress(&cinfo); exit: jpeg_destroy_decompress(&cinfo); GP_ProgressCallbackDone(callback); if (img) *img = ret; return 0; err2: GP_ContextFree(ret); err1: jpeg_destroy_decompress(&cinfo); errno = err; return 1; }
int GP_ReadGIFEx(GP_IO *io, GP_Context **img, GP_DataStorage *storage, GP_ProgressCallback *callback) { GifFileType *gf; GifRecordType rec_type; GP_Context *res = NULL; GP_Pixel bg; int32_t x, y; int err; errno = 0; #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 gf = DGifOpen(io, gif_input_func, NULL); #else gf = DGifOpen(io, gif_input_func); #endif if (gf == NULL) { /* * The giflib uses open() so when we got a failure and errno * is set => open() has failed. * * When errno is not set the file content was not valid so we * set errno to EIO. */ if (errno == 0) errno = EIO; return 1; } GP_DEBUG(1, "Have GIF image %ix%i, %i colors, %i bpp", gf->SWidth, gf->SHeight, gf->SColorResolution, gf->SColorMap ? gf->SColorMap->BitsPerPixel : -1); do { if (DGifGetRecordType(gf, &rec_type) != GIF_OK) { //TODO: error handling GP_DEBUG(1, "DGifGetRecordType() error %s (%i)", gif_err_name(gif_err(gf)), gif_err(gf)); err = EIO; goto err1; } GP_DEBUG(2, "Have GIF record type %s", rec_type_name(rec_type)); switch (rec_type) { case EXTENSION_RECORD_TYPE: if ((err = read_extensions(gf))) goto err1; continue; case IMAGE_DESC_RECORD_TYPE: break; default: continue; } if (DGifGetImageDesc(gf) != GIF_OK) { //TODO: error handling GP_DEBUG(1, "DGifGetImageDesc() error %s (%i)", gif_err_name(gif_err(gf)), gif_err(gf)); err = EIO; goto err1; } if (storage) fill_metadata(gf, storage); GP_DEBUG(1, "Have GIF Image left-top %ix%i, width-height %ix%i," " interlace %i, bpp %i", gf->Image.Left, gf->Image.Top, gf->Image.Width, gf->Image.Height, gf->Image.Interlace, gf->Image.ColorMap ? gf->Image.ColorMap->BitsPerPixel : -1); if (!img) break; res = GP_ContextAlloc(gf->SWidth, gf->SHeight, GP_PIXEL_RGB888); if (res == NULL) { err = ENOMEM; goto err1; } /* If background color is defined, use it */ if (get_bg_color(gf, &bg)) { GP_DEBUG(1, "Filling bg color %x", bg); GP_Fill(res, bg); } /* Now finally read gif image data */ for (y = gf->Image.Top; y < gf->Image.Height; y++) { uint8_t line[gf->Image.Width]; DGifGetLine(gf, line, gf->Image.Width); unsigned int real_y = y; if (gf->Image.Interlace == 64) { real_y = interlace_real_y(gf, y); GP_DEBUG(3, "Interlace y -> real_y %u %u", y, real_y); } //TODO: just now we have only 8BPP for (x = 0; x < gf->Image.Width; x++) GP_PutPixel_Raw_24BPP(res, x + gf->Image.Left, real_y, get_color(gf, line[x])); if (GP_ProgressCallbackReport(callback, y - gf->Image.Top, gf->Image.Height, gf->Image.Width)) { GP_DEBUG(1, "Operation aborted"); err = ECANCELED; goto err2; } } //TODO: now we exit after reading first image break; } while (rec_type != TERMINATE_RECORD_TYPE); DGifCloseFile(gf); /* No Image record found :( */ if (img && !res) { errno = EINVAL; return 1; } if (img) *img = res; return 0; err2: GP_ContextFree(res); err1: DGifCloseFile(gf); errno = err; return 1; }