#include <errno.h>
#include <png.h>
+#include <jpeglib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
}
-
-
-
-
-
//static BCCounter counter;
VFramePng::VFramePng(unsigned char *png_data, double s)
is_keyframe = 0;
pixel_rgb = 0x000000; // BLACK
pixel_yuv = 0x008080;
+ draw_alpha = 1.f;
+ draw_flags = ALIAS_OFF;
stipple = 0;
+ clear_color = 0x000000;
+ clear_alpha = 0x00;
if(do_opengl)
{
void VFrame::get_temp(VFrame *&vfrm, int w, int h, int color_model)
{
- if( vfrm && ( vfrm->get_w() != w || vfrm->get_h() != h ) ) {
+ if( vfrm && ( vfrm->color_model != color_model ||
+ vfrm->get_w() != w || vfrm->get_h() != h ) ) {
delete vfrm; vfrm = 0;
}
if( !vfrm ) vfrm = new VFrame(w, h, color_model, 0);
long VFrame::get_data_size()
{
- return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
+ return calculate_data_size(w, h, bytes_per_line, color_model) - BC_COLOR_ALIGN;
}
long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
bytes_per_line : this->bytes_per_pixel * w;
// Allocate data + padding for MMX
- if(data) {
+ if( data ) {
//printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
memory_type = VFrame::SHARED;
this->data = data;
this->u_offset = u_offset;
this->v_offset = v_offset;
}
- else if(shmid >= 0) {
+ else if( shmid >= 0 ) {
memory_type = VFrame::SHMGET;
this->data = (unsigned char*)shmat(shmid, NULL, 0);
+ if( this->data == (unsigned char*)-1 ) {
+ printf("VFrame::allocate_data %d could not attach"
+ " shared memory, %dx%d (model %d) shmid=0x%08x\n",
+ __LINE__, w, h, color_model, shmid);
+ BC_Trace::dump_shm_stats(stdout);
+ exit(1);
+ }
//printf("VFrame::allocate_data %d shmid=%d data=%p\n", __LINE__, shmid, this->data);
this->shmid = shmid;
this->y_offset = y_offset;
this->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
if( this->shmid >= 0 ) {
this->data = (unsigned char*)shmat(this->shmid, NULL, 0);
-//printf("VFrame::allocate_data %d %d %d %p\n", __LINE__, size, this->shmid, this->data);
-// This causes it to automatically delete when the program exits.
- shmctl(this->shmid, IPC_RMID, 0);
+ if( this->data == (unsigned char *)-1 ) this->data = 0;
}
- else {
+ if( !this->data ) {
printf("VFrame::allocate_data %d could not allocate"
" shared memory, %dx%d (model %d) size=0x%08x\n",
__LINE__, w, h, color_model, size);
BC_Trace::dump_shm_stats(stdout);
+ exit(1);
}
+// This causes it to automatically delete when the program exits.
+ shmctl(this->shmid, IPC_RMID, 0);
}
-// Have to use malloc for libpng
- if( !this->data ) {
+ else {
this->data = (unsigned char *)malloc(size);
+ if( !this->data ) {
+ printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
+ exit(1);
+ }
this->shmid = -1;
}
// Memory check
// printf("VFrame::allocate_data 2 this=%p w=%d h=%d this->data=%p\n",
// this, this->w, this->h, this->data);
- if(!this->data)
- printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
#ifdef LEAKER
printf("==new %p from %p sz %d\n", this->data, __builtin_return_address(0), size);
#endif
int VFrame::allocate_compressed_data(long bytes)
{
- if(bytes < 1) return 1;
+ if( bytes < 1 ) return 1;
// Want to preserve original contents
- if(data && compressed_allocated < bytes)
- {
+ if( data && compressed_allocated < bytes ) {
int new_shmid = -1;
unsigned char *new_data = 0;
- if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
- {
- new_shmid = shmget(IPC_PRIVATE,
- bytes,
- IPC_CREAT | 0777);
- new_data = (unsigned char*)shmat(new_shmid, NULL, 0);
+ if( BC_WindowBase::get_resources()->use_vframe_shm() && use_shm ) {
+ new_shmid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777);
+ if( new_shmid >= 0 ) {
+ new_data = (unsigned char *) shmat(new_shmid, NULL, 0);
+ if( new_data == (unsigned char *)-1 ) new_data = 0;
+ }
+ if( !new_data ) {
+ printf("VFrame::allocate_compressed_data %d could not allocate"
+ " shared memory, %ld\n", __LINE__, bytes);
+ BC_Trace::dump_shm_stats(stdout);
+ exit(1);
+ }
shmctl(new_shmid, IPC_RMID, 0);
}
- else
- {
+ else {
// Have to use malloc for libpng
new_data = (unsigned char *)malloc(bytes);
+ if( !new_data ) {
+ printf("VFrame::allocate_compressed_data %ld: memory exhausted.\n", bytes);
+ exit(1);
+ }
}
bcopy(data, new_data, compressed_allocated);
UNBUFFER(data);
- if(memory_type == VFrame::PRIVATE)
- {
- if(shmid > 0) {
- if(data)
- shmdt(data);
+ if( memory_type == VFrame::PRIVATE ) {
+ if( shmid > 0 ) {
+ if( data ) shmdt(data);
}
else
free(data);
}
- else
- if(memory_type == VFrame::SHMGET)
- {
- if(data)
- shmdt(data);
+ else if( memory_type == VFrame::SHMGET ) {
+ if( data ) shmdt(data);
}
data = new_data;
shmid = new_shmid;
compressed_allocated = bytes;
}
- else
- if(!data)
- {
- if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
- {
- shmid = shmget(IPC_PRIVATE,
- bytes,
- IPC_CREAT | 0777);
- data = (unsigned char*)shmat(shmid, NULL, 0);
+ else if( !data ) {
+ if( BC_WindowBase::get_resources()->use_vframe_shm() && use_shm ) {
+ shmid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777);
+ if( shmid >= 0 ) {
+ data = (unsigned char *)shmat(shmid, NULL, 0);
+ if( data == (unsigned char *)-1 ) data = 0;
+ }
+ if( !data ) {
+ printf("VFrame::allocate_compressed_data %d: could not allocate"
+ " shared memory, %ld\n", __LINE__, bytes);
+ BC_Trace::dump_shm_stats(stdout);
+ exit(1);
+ }
shmctl(shmid, IPC_RMID, 0);
}
- else
- {
+ else {
// Have to use malloc for libpng
data = (unsigned char *)malloc(bytes);
+ if( !data ) {
+ printf("VFrame::allocate_compressed_data %d: memory exhausted, %ld\n",
+ __LINE__, bytes);
+ exit(1);
+ }
}
compressed_allocated = bytes;
if (src_color_model == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8)
png_set_expand(png_ptr);
- if (src_color_model == PNG_COLOR_TYPE_GRAY ||
- src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
+ if (src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
/* expand paletted or RGB images with transparency to full alpha channels
png_set_expand(png_ptr);
}
- switch(src_color_model)
- {
- case PNG_COLOR_TYPE_GRAY:
- case PNG_COLOR_TYPE_RGB:
- new_color_model = BC_RGB888;
- break;
-
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- case PNG_COLOR_TYPE_RGB_ALPHA:
- default:
- new_color_model = BC_RGBA8888;
- break;
-
- case PNG_COLOR_TYPE_PALETTE:
- if(have_alpha)
- new_color_model = BC_RGBA8888;
- else
- new_color_model = BC_RGB888;
+ switch(src_color_model) {
+ case PNG_COLOR_TYPE_GRAY:
+ new_color_model = BC_GREY8;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ new_color_model = BC_RGB888;
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ new_color_model = have_alpha ? BC_RGBA8888 : BC_RGB888;
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ default:
+ new_color_model = BC_RGBA8888;
+ break;
}
-
reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
//printf("VFrame::read_png %d %d %d %p\n", __LINE__, w, h, get_rows());
return 1;
}
int ww = w * xscale, hh = h * yscale;
+ if( ww < 1 ) ww = 1;
+ if( hh < 1 ) hh = 1;
if( ww != w || hh != h ) {
VFrame vframe(*this);
reallocate(NULL, -1, 0, 0, 0, ww, hh, color_model, -1);
return 0;
}
+void VFrame::write_ppm(VFrame *vfrm, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ char fn[BCTEXTLEN];
+ vsnprintf(fn, sizeof(fn), fmt, ap);
+ va_end(ap);
+ FILE *fp = fopen(fn,"w");
+ if( !fp ) { perror("write_ppm"); return; }
+ VFrame *frm = vfrm;
+ if( frm->get_color_model() != BC_RGB888 ) {
+ frm = new VFrame(frm->get_w(), frm->get_h(), BC_RGB888);
+ frm->transfer_from(vfrm);
+ }
+ int w = frm->get_w(), h = frm->get_h();
+ fprintf(fp,"P6\n%d %d\n255\n",w,h);
+ unsigned char **rows = frm->get_rows();
+ for( int i=0; i<h; ++i ) fwrite(rows[i],3,w,fp);
+ fclose(fp);
+ if( frm != vfrm ) delete frm;
+}
+
#define ZERO_YUV(components, type, max) \
{ \
} \
}
-int VFrame::clear_frame()
+void VFrame::black_frame()
{
int sz = w * h;
-//printf("VFrame::clear_frame %d\n", __LINE__);
+//printf("VFrame::black_frame %d\n", __LINE__);
switch(color_model) {
case BC_COMPRESSED:
break;
bzero(data, calculate_data_size(w, h, bytes_per_line, color_model));
break;
}
- return 0;
+}
+
+void VFrame::set_clear_color(int color, int alpha)
+{
+ clear_color = color;
+ clear_alpha = alpha;
+}
+int VFrame::get_clear_color() { return clear_color; }
+int VFrame::get_clear_alpha() { return clear_alpha; }
+
+void VFrame::clear_frame()
+{
+ if( clear_color >= 0 &&
+ !BC_CModels::init_color(clear_color, clear_alpha,
+ get_rows(), get_color_model(), get_y(), get_u(), get_v(),
+ 0,0, get_w(),get_h(), get_bytes_per_line()) )
+ return;
+ black_frame();
}
void VFrame::rotate90()
int VFrame::copy_from(VFrame *frame)
{
- if(this->w != frame->get_w() ||
- this->h != frame->get_h())
- {
+ if( this->w != frame->get_w() ||
+ this->h != frame->get_h() ) {
printf("VFrame::copy_from %d sizes differ src %dx%d != dst %dx%d\n",
- __LINE__,
- frame->get_w(),
- frame->get_h(),
- get_w(),
- get_h());
+ __LINE__, frame->get_w(), frame->get_h(), get_w(), get_h());
return 1;
}
int h = MIN(this->h, frame->get_h());
timestamp = frame->timestamp;
- switch(frame->color_model)
- {
- case BC_COMPRESSED:
- allocate_compressed_data(frame->compressed_size);
- memcpy(data, frame->data, frame->compressed_size);
- this->compressed_size = frame->compressed_size;
- break;
+ switch( frame->color_model ) {
+ case BC_COMPRESSED:
+ allocate_compressed_data(frame->compressed_size);
+ memcpy(data, frame->data, frame->compressed_size);
+ this->compressed_size = frame->compressed_size;
+ break;
- case BC_YUV410P:
- memcpy(get_y(), frame->get_y(), w * h);
- memcpy(get_u(), frame->get_u(), w / 4 * h / 4);
- memcpy(get_v(), frame->get_v(), w / 4 * h / 4);
- break;
+ case BC_YUV410P:
+ memcpy(get_y(), frame->get_y(), w * h);
+ memcpy(get_u(), frame->get_u(), w / 4 * h / 4);
+ memcpy(get_v(), frame->get_v(), w / 4 * h / 4);
+ break;
- case BC_YUV420P:
- case BC_YUV420PI:
- case BC_YUV411P:
+ case BC_YUV420P:
+ case BC_YUV420PI:
+ case BC_YUV411P:
//printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
- memcpy(get_y(), frame->get_y(), w * h);
- memcpy(get_u(), frame->get_u(), w * h / 4);
- memcpy(get_v(), frame->get_v(), w * h / 4);
- break;
+ memcpy(get_y(), frame->get_y(), w * h);
+ memcpy(get_u(), frame->get_u(), w * h / 4);
+ memcpy(get_v(), frame->get_v(), w * h / 4);
+ break;
- case BC_YUV422P:
+ case BC_YUV422P:
//printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
- memcpy(get_y(), frame->get_y(), w * h);
- memcpy(get_u(), frame->get_u(), w * h / 2);
- memcpy(get_v(), frame->get_v(), w * h / 2);
- break;
+ memcpy(get_y(), frame->get_y(), w * h);
+ memcpy(get_u(), frame->get_u(), w * h / 2);
+ memcpy(get_v(), frame->get_v(), w * h / 2);
+ break;
- case BC_YUV444P:
+ case BC_YUV444P:
//printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
- memcpy(get_y(), frame->get_y(), w * h);
- memcpy(get_u(), frame->get_u(), w * h);
- memcpy(get_v(), frame->get_v(), w * h);
- break;
- default:
-// printf("VFrame::copy_from %d\n", calculate_data_size(w,
-// h,
-// -1,
-// frame->color_model));
+ memcpy(get_y(), frame->get_y(), w * h);
+ memcpy(get_u(), frame->get_u(), w * h);
+ memcpy(get_v(), frame->get_v(), w * h);
+ break;
+ default:
+// printf("VFrame::copy_from %d\n", calculate_data_size(w, h, -1, frame->color_model));
// Copy without extra 4 bytes in case the source is a hardware device
- memmove(data, frame->data, get_data_size());
- break;
+ memmove(data, frame->data, get_data_size());
+ break;
}
return 0;
timestamp = that->timestamp;
copy_params(that);
- if( this->get_color_model() == that->get_color_model() &&
+ if( in_x == 0 && in_y == 0 && in_w == that->get_w() && in_h == that->get_h() &&
+ bg_color == 0 && this->get_color_model() == that->get_color_model() &&
this->get_w() == that->get_w() && this->get_h() == that->get_h() &&
this->get_bytes_per_line() == that->get_bytes_per_line() )
return this->copy_from(that);
// a (~alpha) transparency, 0x00==solid .. 0xff==transparent
void VFrame::set_pixel_color(int rgb, int a)
{
- pixel_rgb = (rgb&0xffffff) | ~a<<24;
+ pixel_rgb = (~a<<24) | (rgb&0xffffff);
int ir = 0xff & (pixel_rgb >> 16);
int ig = 0xff & (pixel_rgb >> 8);
int ib = 0xff & (pixel_rgb >> 0);
YUV::yuv.rgb_to_yuv_8(ir, ig, ib);
- pixel_yuv = (~a<<24) | (ir<<16) | (ig<<8) | (ib<<0);
+ pixel_yuv = (~a<<24) | (ir<<16) | (ig<<8) | (ib<<0);
}
void VFrame::set_stiple(int mask)
{
stipple = mask;
}
-
-int VFrame::draw_pixel(int x, int y)
+void VFrame::set_draw_alpha(float alpha)
{
- if( x < 0 || y < 0 || x >= get_w() || y >= get_h() ) return 1;
-
-#define DRAW_PIXEL(type, r, g, b, comps, a) { \
- type **rows = (type**)get_rows(); \
- type *rp = rows[y], *bp = rp + x*comps; \
- bp[0] = r; \
- if( comps > 1 ) { bp[1] = g; bp[2] = b; } \
- if( comps == 4 ) bp[3] = a; \
+ draw_alpha = alpha;
+}
+void VFrame::set_draw_flags(int flags)
+{
+ draw_flags = flags;
}
+
+int VFrame::draw_pixel(float x, float y, float a)
+{
+ int ix = x, iy = y;
+ if( ix < 0 || iy < 0 || ix >= get_w() || iy >= get_h() ) return 1;
+ if( a <= 0 ) return 0;
+ if( a > 1 ) a = 1;
+ int color = BC_CModels::is_yuv(color_model) ? pixel_yuv : pixel_rgb;
float fr = 0, fg = 0, fb = 0, fa = 0;
- int pixel_color = BC_CModels::is_yuv(color_model) ? pixel_yuv : pixel_rgb;
- int ir = (0xff & (pixel_color >> 16));
- int ig = (0xff & (pixel_color >> 8));
- int ib = (0xff & (pixel_color >> 0));
- int ia = (0xff & (pixel_color >> 24)) ^ 0xff; // transparency, not opacity
- if( (x+y) & stipple ) {
+ int ir = (0xff & (color >> 16));
+ int ig = (0xff & (color >> 8));
+ int ib = (0xff & (color >> 0));
+ int ia = (0xff & ~(color >> 24)); // transparency, not opacity
+ if( (ix+iy) & stipple ) {
ir = 255 - ir; ig = 255 - ig; ib = 255 - ib;
}
int rr = (ir<<8) | ir, gg = (ig<<8) | ig, bb = (ib<<8) | ib, aa = (ia<<8) | ia;
+ float fmax = 65535.f; fa = aa/fmax;
if( BC_CModels::is_float(color_model) ) {
- fr = rr/65535.f; fg = gg/65535.f; fb = bb/65535.f; fa = aa/65535.f;
+ fr = rr/fmax; fg = gg/fmax; fb = bb/fmax;
}
+#define DRAW_PIXEL(cmdl, type, r, g, b, ofs, max, comps) \
+case cmdl: { \
+ float src_a = fa*draw_alpha, src_1a = 1 - src_a; \
+ type **rows = (type**)get_rows(); \
+ type *rp = rows[iy], *bp = rp + ix*comps; \
+ bp[0] = src_a * r + src_1a * bp[0]; \
+ if( comps > 1 ) { \
+ bp[1] = src_a * (g-ofs) + src_1a * (bp[1]-ofs) + ofs; \
+ bp[2] = src_a * (b-ofs) + src_1a * (bp[2]-ofs) + ofs; \
+ } \
+ if( comps == 4 ) \
+ bp[3] = src_a * max + src_1a * bp[3]; \
+ break;\
+}
+
switch(get_color_model()) {
- case BC_A8:
- DRAW_PIXEL(uint8_t, ib, 0, 0, 1, 0);
- break;
- case BC_RGB888:
- case BC_YUV888:
- DRAW_PIXEL(uint8_t, ir, ig, ib, 3, 0);
- break;
- case BC_RGBA8888:
- case BC_YUVA8888:
- DRAW_PIXEL(uint8_t, ir, ig, ib, 4, ia);
- break;
- case BC_RGB161616:
- case BC_YUV161616:
- DRAW_PIXEL(uint16_t, rr, gg, bb, 3, 0);
- break;
- case BC_RGBA16161616:
- case BC_YUVA16161616:
- DRAW_PIXEL(uint16_t, rr, gg, bb, 4, aa);
- break;
- case BC_RGB_FLOAT:
- DRAW_PIXEL(float, fr, fg, fb, 3, 0);
- break;
- case BC_RGBA_FLOAT:
- DRAW_PIXEL(float, fr, fg, fb, 4, fa);
- break;
+ DRAW_PIXEL(BC_A8, uint8_t, ib, 0, 0, 0x00, 0xff, 1);
+ DRAW_PIXEL(BC_RGB888, uint8_t, ir, ig, ib, 0x00, 0xff, 3);
+ DRAW_PIXEL(BC_YUV888, uint8_t, ir, ig, ib, 0x80, 0xff, 3);
+ DRAW_PIXEL(BC_RGBA8888, uint8_t, ir, ig, ib, 0x00, 0xff, 4);
+ DRAW_PIXEL(BC_YUVA8888, uint8_t, ir, ig, ib, 0x80, 0xff, 4);
+ DRAW_PIXEL(BC_RGB161616, uint16_t, rr, gg, bb, 0x0000, 0xffff, 3);
+ DRAW_PIXEL(BC_YUV161616, uint16_t, rr, gg, bb, 0x8000, 0xffff, 3);
+ DRAW_PIXEL(BC_RGBA16161616, uint16_t, rr, gg, bb, 0x0000, 0xffff, 4);
+ DRAW_PIXEL(BC_YUVA16161616, uint16_t, rr, gg, bb, 0x8000, 0xffff, 4);
+ DRAW_PIXEL(BC_RGB_FLOAT, float, fr, fg, fb, 0., 1., 3);
+ DRAW_PIXEL(BC_RGBA_FLOAT, float, fr, fg, fb, 0., 1., 4);
}
return 0;
}
+int VFrame::draw_pixel(float x, float y, float frac, int axis)
+{
+ if( draw_flags ) {
+ int xs = axis, ys = 1-axis;
+ if( draw_flags & ALIAS_TOP ) draw_pixel(x-xs, y-ys, 1-frac);
+ draw_pixel(x, y, draw_flags & ALIAS_CTR ? 1-frac : 1);
+ if( draw_flags & ALIAS_BOT ) draw_pixel(x+xs, y+ys, frac);
+ }
+ else
+ draw_pixel(x, y);
+ return 0;
+}
-// Bresenham's
-void VFrame::draw_line(int x1, int y1, int x2, int y2)
+void VFrame::draw_line(float x1, float y1, float x2, float y2)
{
if( y1 > y2 ) {
int tx = x1; x1 = x2; x2 = tx;
int ty = y1; y1 = y2; y2 = ty;
}
-
- int x = x1, y = y1;
- int dx = x2-x1, dy = y2-y1;
- int dx2 = 2*dx, dy2 = 2*dy;
- if( dx < 0 ) dx = -dx;
- int r = dx > dy ? dx : dy, n = r;
- int dir = 0;
- if( dx2 < 0 ) dir += 1;
- if( dy >= dx ) {
- if( dx2 >= 0 ) do { /* +Y, +X */
- draw_pixel(x, y++);
- if( (r -= dx2) < 0 ) { r += dy2; ++x; }
- } while( --n >= 0 );
- else do { /* +Y, -X */
- draw_pixel(x, y++);
- if( (r += dx2) < 0 ) { r += dy2; --x; }
- } while( --n >= 0 );
+ float dx = x2-x1, dy = y2-y1;
+ float s = dx ? dy/dx : 1;
+ float t = dy ? dx/dy : 0;
+ int xs = dx < 0 ? -1 : 1;
+ dx *= xs;
+ int idx = (int)x2 - (int)x1;
+ int idy = (int)y2 - (int)y1;
+ int d = dx >= dy ? abs(idx) : idy;
+ float x = x1, y = y1;
+ if( dx > dy ) {
+ draw_pixel(x, y, y-(int)y, 0);
+ while( --d >= 0 ) {
+ y = y1 + ((x += xs) - x1) * s;
+ draw_pixel(x, y, y-(int)y, 0);
+ }
}
else {
- if( dx2 >= 0 ) do { /* +X, +Y */
- draw_pixel(x++, y);
- if( (r -= dy2) < 0 ) { r += dx2; ++y; }
- } while( --n >= 0 );
- else do { /* -X, +Y */
- draw_pixel(x--, y);
- if( (r -= dy2) < 0 ) { r -= dx2; ++y; }
- } while( --n >= 0 );
+ draw_pixel(x, y, x-(int)x, 1);
+ while( --d >= 0 ) {
+ x = x1 + (++y - y1) * t;
+ draw_pixel(x, y, x-(int)x, 1);
+ }
}
}
if( abs(rr) < abs(r) )
moveX(rr);
}
-xit: vframe->draw_pixel(sx, sy);
+xit:
+// vframe->draw_pixel(sx, sy);
+ float vx = abs(dx), vy = abs(dy);
+ float vv = 4*(vx > vy ? dx : dy);
+ float frac = vv ? -r / vv : 0;
+ frac = (1+frac) / 2;
+ bclamp(frac, 0, 1);
+ int axis = abs(dx) >= abs(dy) ? 1 : 0;
+ vframe->draw_pixel(sx, sy, frac, axis);
}
void VFrame::draw_smooth(int x1, int y1, int x2, int y2, int x3, int y3)
xmxx = ex; xmxy = ey;
}
if( xs > 0 )
- vframe->draw_pixel(sx, sy);
+ vframe->draw_pixel(sx, sy, 0, 0);
while( xs*(sx-xmxx) < 0 && (xs*dx < 0 || rx() < 0) ) {
moveX(rx());
- vframe->draw_pixel(sx, sy);
+ vframe->draw_pixel(sx, sy, 0, 0);
}
}
else if( y1 < y2 && y3 < y2 ) {
smooth_line lt(this), rt(this); // Q on top
lt.init0(x1, y1, x2, y2, x3, y3, 1);
- draw_pixel(lt.sx, lt.sy);
+ draw_pixel(lt.sx, lt.sy, 0, 0);
rt.init0(x1, y1, x2, y2, x3, y3, -1);
- draw_pixel(rt.sx, rt.sy);
+ draw_pixel(rt.sx, rt.sy, 0, 0);
while( !lt.done || !rt.done ) {
lt.draw();
rt.draw();
else {
smooth_line pt(this); // Q in between
pt.init0(x1, y1, x2, y2, x3, y3, 0);
- draw_pixel(pt.sx, pt.sy);
+ draw_pixel(pt.sx, pt.sy, 0, 1);
while( !pt.done ) {
pt.draw();
}
}
+// jpeg decompress
+class jpeg_err : public jpeg_error_mgr
+{
+ static void s_error_exit(j_common_ptr cp);
+ static void s_output_message(j_common_ptr cp);
+public:
+ jpeg_err() {
+ jpeg_std_error((jpeg_error_mgr *)this);
+ error_exit = s_error_exit;
+ output_message = s_output_message;
+ }
+ ~jpeg_err() {}
+};
+
+class jpeg_src : public jpeg_source_mgr
+{
+ static void s_init_source(j_decompress_ptr jp);
+ static boolean s_fill_input_buffer(j_decompress_ptr jp);
+ static void s_skip_input_data(j_decompress_ptr jp, long len);
+ static void s_term_source(j_decompress_ptr jp);
+ static boolean s_resync_to_restart(j_decompress_ptr jp, int v);
+public:
+ jpeg_src();
+ ~jpeg_src();
+ int jpeg_file(int fd);
+ int jpeg_mem(const unsigned char *bfr, long len);
+
+ int fd;
+ unsigned char *mbfr;
+ long mlen;
+ enum { buffer_sz=0x10000, file_sz=0x100000, };
+ unsigned char *buffer;
+ boolean fill_buffer();
+ void skip_data(long len);
+};
+
+class JpegVFrame : public jpeg_decompress_struct
+{
+public:
+ JpegVFrame();
+ ~JpegVFrame();
+ int read_jpeg(VFrame *vfrm, double xs, double ys, int jpeg_model);
+
+ jpeg_err jerr;
+ jpeg_src jsrc;
+ int debug, ret;
+};
+
+
+void jpeg_err:: s_error_exit(j_common_ptr cp)
+{
+ JpegVFrame *jpeg = (JpegVFrame *)cp;
+ jpeg->ret = 1;
+ if( !jpeg->debug ) return;
+ printf("s_error_exit()\n");
+}
+
+void jpeg_err::
+s_output_message(j_common_ptr cp)
+{
+ JpegVFrame *jpeg = (JpegVFrame *)cp;
+ if( !jpeg->debug ) return;
+ char msg[JMSG_LENGTH_MAX];
+ (*cp->err->format_message)(cp, msg);
+ printf("s_output_message() = %s\n",&msg[0]);
+}
+
+
+jpeg_src::jpeg_src()
+{
+ init_source = s_init_source;
+ fill_input_buffer = s_fill_input_buffer;
+ skip_input_data = s_skip_input_data;
+ resync_to_restart = s_resync_to_restart;
+ term_source = s_term_source;
+
+ fd = -1;
+ buffer = 0;
+ mbfr = 0;
+ mlen = -1;
+}
+
+jpeg_src::~jpeg_src()
+{
+ if( mbfr ) ::munmap(mbfr, mlen);
+ delete [] buffer;
+}
+
+int jpeg_src::jpeg_file(int fd)
+{
+ this->fd = fd;
+ struct stat st;
+ if( fstat(fd, &st) || !st.st_size ) return 0;
+ if( st.st_size < file_sz ) {
+ mbfr = (unsigned char *)::mmap(0, mlen = st.st_size,
+ PROT_READ, MAP_SHARED, fd, 0);
+ if( mbfr == MAP_FAILED ) return 0;
+ next_input_byte = mbfr;
+ bytes_in_buffer = mlen;
+ }
+ else {
+ buffer = new unsigned char[buffer_sz];
+ next_input_byte = &buffer[0];
+ bytes_in_buffer = 0;
+ }
+ return 1;
+}
+int jpeg_src::jpeg_mem(const unsigned char *bfr, long len)
+{
+ next_input_byte = bfr;
+ bytes_in_buffer = len;
+ return 1;
+}
+
+void jpeg_src::s_init_source(j_decompress_ptr jp) {}
+void jpeg_src::s_term_source(j_decompress_ptr jp) {}
+
+boolean jpeg_src::s_resync_to_restart(j_decompress_ptr jp, int v)
+{
+ return jpeg_resync_to_restart(jp, v);
+}
+
+boolean jpeg_src::s_fill_input_buffer(j_decompress_ptr jp)
+{
+ JpegVFrame *jpeg = (JpegVFrame *)jp;
+ return jpeg->jsrc.fill_buffer();
+}
+
+boolean jpeg_src::fill_buffer()
+{
+ if( mbfr || fd < 0 ) return 0;
+ long n = ::read(fd, buffer, buffer_sz);
+ if( n < 0 ) perror("jpeg read");
+ if( !n ) return 0;
+ next_input_byte = buffer;
+ bytes_in_buffer = n;
+ return 1;
+}
+
+void jpeg_src::s_skip_input_data(j_decompress_ptr jp, long len)
+{
+ JpegVFrame *jpeg = (JpegVFrame *)jp;
+ jpeg->jsrc.skip_data(len);
+}
+
+void jpeg_src::skip_data(long len)
+{
+ while( len > (long) bytes_in_buffer ) {
+ len -= (long) bytes_in_buffer;
+ if( !fill_buffer() ) return;
+ }
+ next_input_byte += len;
+ bytes_in_buffer -= len;
+}
+
+
+JpegVFrame::JpegVFrame()
+{
+ jpeg_create_decompress(this);
+ debug = 1; ret = 0;
+ err = &jerr; src = &jsrc;
+}
+JpegVFrame::~JpegVFrame()
+{
+ jpeg_destroy_decompress(this);
+}
+
+int JpegVFrame::read_jpeg(VFrame *vfrm, double xs, double ys, int jpeg_model)
+{
+ VFrame *xfrm = vfrm;
+ int color_model = xfrm->get_color_model();
+ if( color_model == BC_COMPRESSED ) color_model = jpeg_model;
+ jpeg_abort((jpeg_common_struct *)this);
+ if( jpeg_read_header(this, TRUE) != JPEG_HEADER_OK ) return 0;
+ jpeg_calc_output_dimensions(this);
+ quantize_colors = FALSE;
+ out_color_space =
+ jpeg_model == BC_YUV888 ? JCS_YCbCr :
+ jpeg_model == BC_GREY8 ? JCS_GRAYSCALE : JCS_RGB;
+ jpeg_calc_output_dimensions(this);
+ int w = bmax(image_width*xs, 1.);
+ int h = bmax(image_height*ys, 1.);
+ vfrm->reallocate(0, -1, 0, 0, 0, w, h, color_model, -1);
+ if( w != (int)image_width || h != (int)image_height ||
+ color_model != jpeg_model )
+ xfrm = new VFrame(image_width, image_height, jpeg_model);
+ unsigned char *pic = xfrm->get_data();
+ int linesz = xfrm->get_bytes_per_line();
+ jpeg_start_decompress(this);
+ while( !ret && output_scanline < image_height ) {
+ JSAMPROW rowptr = (JSAMPROW) &pic[output_scanline * linesz];
+ jpeg_read_scanlines(this, &rowptr, (JDIMENSION) 1);
+ }
+ jpeg_finish_decompress(this);
+ if( vfrm != xfrm ) {
+ vfrm->transfer_from(xfrm);
+ delete xfrm;
+ }
+ return 1;
+}
+
+int VFrameJpeg::read_jpeg(const unsigned char *data, long sz,
+ double xscale, double yscale, int jpeg_model)
+{
+ JpegVFrame jpeg;
+ jpeg.jsrc.jpeg_mem(data, sz);
+ return jpeg.read_jpeg(this, xscale, yscale, jpeg_model);
+}
+
+VFrameJpeg::VFrameJpeg(const unsigned char *jpeg_data, double s)
+{
+ long image_size =
+ ((long)jpeg_data[0] << 24) | ((long)jpeg_data[1] << 16) |
+ ((long)jpeg_data[2] << 8) | (long)jpeg_data[3];
+ if( !s ) s = BC_WindowBase::get_resources()->icon_scale;
+ read_jpeg(jpeg_data+4, image_size, s, s, BC_RGB888);
+}
+
+VFrameJpeg::VFrameJpeg(const unsigned char *jpeg_data, long image_size, double xs, double ys)
+{
+ if( !xs ) xs = BC_WindowBase::get_resources()->icon_scale;
+ if( !ys ) ys = BC_WindowBase::get_resources()->icon_scale;
+ read_jpeg(jpeg_data, image_size, xs, ys, BC_RGB888);
+}
+
+VFrameJpeg::~VFrameJpeg()
+{
+}
+
+
+VFrame *VFrameJpeg::vframe_jpeg(int fd, double xs, double ys, int jpeg_model)
+{
+ JpegVFrame jpeg;
+ jpeg.jsrc.jpeg_file(fd);
+ VFrame *vfrm = new VFrame();
+ if( !jpeg.read_jpeg(vfrm, xs, ys, jpeg_model) ) {
+ delete vfrm; vfrm = 0;
+ }
+ return vfrm;
+}
+
+VFrame *VFrameJpeg::vframe_jpeg(const char *jpeg_path, double xs, double ys, int jpeg_model)
+{
+ VFrame *vframe = 0;
+ int fd = ::open(jpeg_path, O_RDONLY);
+ if( fd >= 0 ) {
+ vframe = vframe_jpeg(fd, xs, ys, jpeg_model);
+ ::close(fd);
+ }
+ return vframe;
+}
+