diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index c64e2cb0c..e70d20f8b 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -139,151 +139,101 @@ bool StreamBase::checkCommandQueue() { Image *StreamBase::prepareImage(Image *image) { /* zooming should happen before scaling to preserve quality - * scale is relative to base dimensions, and represents the rough ration between desired view size and base dimensions + * scale is relative to base dimensions, and represents the rough ratio between desired view size and base dimensions */ - - // Do not bother to scale zoomed in images, just crop them and let the browser scale - // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. - bool optimisedScaling = false; - bool image_copied = false; - int mag = (scale * zoom) / ZM_SCALE_BASE; - int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; - - int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; - int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; - int base_image_width = image->Width(), base_image_height = image->Height(); - int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; - int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; - int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; - int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; - int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; - int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; - int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; - - Debug(3, - "Scaling by %d, zooming by %d = magnifying by %d(%d)\n" - "Last scaling by %d, zooming by %d = magnifying by %d(%d)\n" - "Base image width = %d, height = %d\n" - "Virtual image width = %d, height = %d\n" - "Last virtual image width = %d, height = %d\n" - "Actual image width = %d, height = %d\n" - "Last actual image width = %d, height = %d\n" - "Display image width = %d, height = %d\n" - "Last display image width = %d, height = %d\n" - "Send image width = %d, height = %d\n", - scale, zoom, mag, act_mag, - last_scale, last_zoom, last_mag, last_act_mag, - base_image_width, base_image_height, - virt_image_width, virt_image_height, - last_virt_image_width, last_virt_image_height, - act_image_width, act_image_height, - last_act_image_width, last_act_image_height, - disp_image_width, disp_image_height, - last_disp_image_width, last_disp_image_height, - send_image_width, send_image_height - ); - - Debug(3, "Real image width = %d, height = %d", image->Width(), image->Height()); - - if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height ) { - + if (zoom != 100) { + int base_image_width = image->Width(), + base_image_height = image->Height(), + disp_image_width = image->Width() * scale/ZM_SCALE_BASE, + disp_image_height = image->Height() * scale / ZM_SCALE_BASE; /* x and y are scaled by web UI to base dimensions units. - * So if we have scaled the image above, then we need to adjust the click to the new dimensions */ + * When zooming, we blow up the image by the amount 150 for first zoom, right? 150%, then cut out a base sized chunk + * However if we have zoomed before, then we are zooming into the previous cutout + * The box stored in last_crop should be in base_image units, So we need to turn x,y into percentages, then apply to last_crop + */ + if (!last_crop.Hi().x_ or last_crop.Hi().y_) last_crop = Box({0, 0}, {base_image_width, base_image_height}); - if (zoom) { - /* When zooming, we blow up the image by the amount 150 for first zoom, right? 150%, then cut out a base sized chunk - * However if we have zoomed before, then we are zooming into the previous cutout - * The box stored in last_crop should be in base_image units, So we need to turn x,y into percentages, then apply to last_crop - * - */ - if (!last_crop.Hi().x_ or last_crop.Hi().y_) last_crop = Box({0, 0}, {base_image_width, base_image_height}); + double x_percent = static_cast(x * ZM_SCALE_BASE) / base_image_width; + double y_percent = static_cast(y * ZM_SCALE_BASE) / base_image_height; + Debug(2, "click percent %dx%d => %.2fx%.2f", x, y, x_percent, y_percent); - double x_percent = static_cast(x * ZM_SCALE_BASE) / base_image_width; - double y_percent = static_cast(y * ZM_SCALE_BASE) / base_image_height; - Debug(2, "click percent %dx%d => %.2fx%.2f", x, y, x_percent, y_percent); + // If we were previously zoomed in, then the coordinate percentages are into the crop, so calculate the click coordinates in base image + int crop_x = last_crop.Lo().x_ + (x_percent * last_crop.Width() / ZM_SCALE_BASE); + int crop_y = last_crop.Lo().y_ + (y_percent * last_crop.Height() / ZM_SCALE_BASE); + Debug(2, "crop click %dx%d => %dx%d out of %dx%d", x, y, crop_x, crop_y, last_crop.Width(), last_crop.Height()); - // If we were previously zoomed in, then the coordinate percentages are into the crop, so calculate the click coordinates in base image - int crop_x = last_crop.Lo().x_ + (x_percent * last_crop.Width() / ZM_SCALE_BASE); - int crop_y = last_crop.Lo().y_ + (y_percent * last_crop.Height() / ZM_SCALE_BASE); - Debug(2, "crop click %dx%d => %dx%d out of %dx%d", x, y, crop_x, crop_y, last_crop.Width(), last_crop.Height()); + int zoom_image_width = base_image_width * zoom / ZM_SCALE_BASE, + zoom_image_height = base_image_height * zoom / ZM_SCALE_BASE, + click_x = crop_x * zoom / ZM_SCALE_BASE, + click_y = crop_y * zoom / ZM_SCALE_BASE; + Debug(2, "adjusted click %dx%d * %d zoom => %dx%d out of %dx%d", x, y, zoom, click_x, click_y, zoom_image_width, zoom_image_height); - int zoom_image_width = base_image_width * zoom / ZM_SCALE_BASE, - zoom_image_height = base_image_height * zoom / ZM_SCALE_BASE, - click_x = crop_x * zoom / ZM_SCALE_BASE, - click_y = crop_y * zoom / ZM_SCALE_BASE; - Debug(2, "adjusted click %dx%d * %d zoom => %dx%d out of %dx%d", x, y, zoom, click_x, click_y, zoom_image_width, zoom_image_height); + // These can go out of image. Resulting size will be less than base image. That's ok. + // We don't want to center it, we want to keep the relative offset from center where the click is. + int left_dist = base_image_width * x_percent/ZM_SCALE_BASE; + int top_dist = base_image_height * y_percent/ZM_SCALE_BASE; + Debug(2, "Dest at %d,%d", left_dist, top_dist); - // These can go out of image. Resulting size will be less than base image. That's ok. - // We don't want to center it, we want to keep the relative offset from center where the click is. - int left_dist = base_image_width * x_percent/ZM_SCALE_BASE; - int top_dist = base_image_height * y_percent/ZM_SCALE_BASE; - Debug(2, "Dest at %d,%d", left_dist, top_dist); + int lo_x = click_x - left_dist; + int hi_x = lo_x + base_image_width; + Debug(2, "hi_x = lo_x %d + base_image_width %d - left_dist %d = %d", lo_x, base_image_width, left_dist, hi_x); + int lo_y = click_y - top_dist; + int hi_y = lo_y + base_image_height; + Debug(2, "hi_y = lo_y %d + base_image_h %d - top_dist %d = %d", lo_y, base_image_height, top_dist, hi_y); - int lo_x = click_x - left_dist; - int hi_x = lo_x + base_image_width; - Debug(2, "hi_x = lo_x %d + base_image_width %d - left_dist %d = %d", lo_x, base_image_width, left_dist, hi_x); - int lo_y = click_y - top_dist; - int hi_y = lo_y + base_image_height; - Debug(2, "hi_y = lo_y %d + base_image_h %d - top_dist %d = %d", lo_y, base_image_height, top_dist, hi_y); + int amount_to_shrink_y = 0; + if (lo_x < 0) { + amount_to_shrink_y = (-1 * lo_x) * base_image_height / base_image_width; + lo_x = 0; + } else if (hi_x >= zoom_image_width) { + amount_to_shrink_y = (hi_x - zoom_image_width) * base_image_height / base_image_width; + hi_x = zoom_image_width - 1; + } + Debug(1, "Shrinking y by %d from %d,%d to %d,%d", amount_to_shrink_y, lo_y, hi_y, lo_y+(amount_to_shrink_y/2), hi_y-(amount_to_shrink_y/2)); + if (amount_to_shrink_y) { + lo_y += amount_to_shrink_y/2; + hi_y -= amount_to_shrink_y/2; + } - int amount_to_shrink_y = 0; - if (lo_x < 0) { - amount_to_shrink_y = (-1 * lo_x) * base_image_height / base_image_width; - lo_x = 0; - } else if (hi_x >= zoom_image_width) { - amount_to_shrink_y = (hi_x - zoom_image_width) * base_image_height / base_image_width; - hi_x = zoom_image_width - 1; - } - Debug(1, "Shrinking y by %d from %d,%d to %d,%d", amount_to_shrink_y, lo_y, hi_y, lo_y+(amount_to_shrink_y/2), hi_y-(amount_to_shrink_y/2)); - if (amount_to_shrink_y) { - lo_y += amount_to_shrink_y/2; - hi_y -= amount_to_shrink_y/2; - } + int amount_to_shrink_x = 0; + if (lo_y < 0) { + amount_to_shrink_x = (-1 * lo_y) * base_image_width / base_image_height; + Debug(1, "%d to %d = %d", lo_y, -1*lo_y, amount_to_shrink_x); + lo_y = 0; + } else if (hi_y >= zoom_image_height) { + amount_to_shrink_x = (hi_y - zoom_image_height) * base_image_width / base_image_height; + hi_y = zoom_image_height - 1; + } + Debug(1, "Shrinking x by %d from %d,%d to %d,%d", amount_to_shrink_x, lo_x, hi_x, lo_x+(amount_to_shrink_x/2), hi_x-(amount_to_shrink_x/2)); + if (amount_to_shrink_x) { + lo_x += amount_to_shrink_x/2; + hi_x -= amount_to_shrink_x/2; + } - int amount_to_shrink_x = 0; - if (lo_y < 0) { - amount_to_shrink_x = (-1 * lo_y) * base_image_width / base_image_height; - Debug(1, "%d to %d = %d", lo_y, -1*lo_y, amount_to_shrink_x); - lo_y = 0; - } else if (hi_y >= zoom_image_height) { - amount_to_shrink_x = (hi_y - zoom_image_height) * base_image_width / base_image_height; - hi_y = zoom_image_height - 1; - } - Debug(1, "Shrinking x by %d from %d,%d to %d,%d", amount_to_shrink_x, lo_x, hi_x, lo_x+(amount_to_shrink_x/2), hi_x-(amount_to_shrink_x/2)); - if (amount_to_shrink_x) { - lo_x += amount_to_shrink_x/2; - hi_x -= amount_to_shrink_x/2; - } + Debug(3, "Cropping to %d,%d -> %d,%d %dx%din blown up image", lo_x, lo_y, hi_x, hi_y, hi_x-lo_x, hi_y-lo_y); + // Scaled back to base_image dimensions + last_crop = Box({lo_x*ZM_SCALE_BASE/zoom, lo_y*ZM_SCALE_BASE/zoom}, {hi_x*ZM_SCALE_BASE/zoom, hi_y*ZM_SCALE_BASE/zoom}); - Debug(3, "Cropping to %d,%d -> %d,%d %dx%din blown up image", lo_x, lo_y, hi_x, hi_y, hi_x-lo_x, hi_y-lo_y); - // Scaled back to base_image dimensions - last_crop = Box({lo_x*ZM_SCALE_BASE/zoom, lo_y*ZM_SCALE_BASE/zoom}, {hi_x*ZM_SCALE_BASE/zoom, hi_y*ZM_SCALE_BASE/zoom}); - - Debug(3, "Cropping to %d,%d -> %d,%d", last_crop.Lo().x_, last_crop.Lo().y_, last_crop.Hi().x_, last_crop.Hi().y_); - if ( !image_copied ) { - static Image copy_image; - copy_image.Assign(*image); - image = ©_image; - image_copied = true; - } - image->Crop(last_crop); - image->Scale(disp_image_width, disp_image_height); - } else - //} // end if ( mag != last_mag || x != last_x || y != last_y ) - - if ( ( mag != ZM_SCALE_BASE ) && (act_mag != ZM_SCALE_BASE) ) { - Debug(3, "Magnifying by %d from %dx%d", mag, image->Width(), image->Height()); + Debug(3, "Cropping to %d,%d -> %d,%d", last_crop.Lo().x_, last_crop.Lo().y_, last_crop.Hi().x_, last_crop.Hi().y_); + if ( !image_copied ) { static Image copy_image; copy_image.Assign(*image); image = ©_image; image_copied = true; - image->Scale(mag); - Debug(3, "Magnifying by %d to %dx%d", mag, image->Width(), image->Height()); } - } // end if difference in image vs displayed dimensions - Debug(3, "Sending %dx%d", image->Width(), image->Height()); + image->Crop(last_crop); + image->Scale(disp_image_width, disp_image_height); + } else if (scale != ZM_SCALE_BASE) { + Debug(3, "scaling by %d from %dx%d", scale, image->Width(), image->Height()); + static Image copy_image; + copy_image.Assign(*image); + image = ©_image; + image_copied = true; + image->Scale(scale); + } + Debug(3, "Sending %dx%d", image->Width(), image->Height()); last_scale = scale; last_zoom = zoom;