static ssize_t sub_read(gp_io *io, void *buf, size_t size) { struct sub_io *sub_io = GP_IO_PRIV(io); if (sub_io->cur > sub_io->end) { GP_BUG("Current offset (%zi) is after the end (%zi)", sub_io->cur, sub_io->end); errno = EINVAL; return 0; } size_t io_size = sub_io->end - sub_io->cur; size = GP_MIN(size, io_size); if (size == 0) return 0; ssize_t ret = gp_io_read(sub_io->io, buf, size); if (ret < 0) return ret; sub_io->cur += ret; return ret; }
/* * The interlacing consists of 8 pixel high strips. Each pass adds some lines * into each strip. This function maps y in the gif buffer to real y. */ static inline unsigned int interlace_real_y(GifFileType *gf, unsigned int y) { const unsigned int h = gf->Image.Height; unsigned int real_y; /* Pass 1: Line 0 for each strip */ real_y = 8 * y; if (real_y < h) return real_y; /* Pass 2: Line 4 for each strip */ real_y = 8 * (y - (h - 1)/8 - 1) + 4; if (real_y < h) return real_y; /* Pass 3: Lines 2 and 6 */ real_y = 4 * (y - (h - 1)/4 - 1) + 2; if (real_y < h) return real_y; /* Pass 4: Lines 1, 3, 5, and 7 */ real_y = 2 * (y - h/2 - h%2) + 1; if (real_y < h) return real_y; GP_BUG("real_y > h"); return 0; }
int GP_WriteJPG(const GP_Context *src, GP_IO *io, GP_ProgressCallback *callback) { struct jpeg_compress_struct cinfo; GP_PixelType out_pix; struct my_jpg_err my_err; struct my_dest_mgr dst; uint8_t buf[1024]; int err; GP_DEBUG(1, "Writing JPG Image to I/O (%p)", io); out_pix = GP_LineConvertible(src->pixel_type, out_pixel_types); if (out_pix == GP_PIXEL_UNKNOWN) { GP_DEBUG(1, "Unsupported pixel type %s", GP_PixelTypeName(src->pixel_type)); errno = ENOSYS; return 1; } if (setjmp(my_err.setjmp_buf)) { errno = EIO; return 1; } cinfo.err = jpeg_std_error(&my_err.error_mgr); my_err.error_mgr.error_exit = my_error_exit; jpeg_create_compress(&cinfo); init_dest_mgr(&dst, io, buf, sizeof(buf)); cinfo.dest = (void*)&dst; cinfo.image_width = src->w; cinfo.image_height = src->h; switch (out_pix) { case GP_PIXEL_BGR888: cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; break; case GP_PIXEL_G8: cinfo.input_components = 1; cinfo.in_color_space = JCS_GRAYSCALE; break; default: GP_BUG("Don't know how to set color_space and compoments"); } jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); if (out_pix != src->pixel_type) err = save_convert(&cinfo, src, out_pix, callback); else err = save(&cinfo, src, callback); if (err) { jpeg_destroy_compress(&cinfo); errno = err; return 1; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); GP_ProgressCallbackDone(callback); return 0; }