Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace libpng and stb_image with PistonDevelopers/image #7933

Merged
merged 3 commits into from Oct 12, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -52,10 +52,6 @@ git = "https://github.com/servo/rust-azure"
[dependencies.layers]
git = "https://github.com/servo/rust-layers"

[dependencies.png]
git = "https://github.com/servo/rust-png"
features = [ "serde-serialization" ]

[dependencies.clipboard]
git = "https://github.com/aweinstock314/rust-clipboard"

@@ -72,6 +68,7 @@ features = [ "serde_serialization" ]

[dependencies]
app_units = "0.1"
image = "0.3.14"
log = "0.3"
num = "0.1.24"
time = "0.1.17"
@@ -16,7 +16,8 @@ use gfx::paint_task::{ChromeToPaintMsg, PaintRequest};
use gfx_traits::color;
use gleam::gl;
use gleam::gl::types::{GLint, GLsizei};
use ipc_channel::ipc;
use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcSharedMemory};
use ipc_channel::router::ROUTER;
use layers::geometry::{DevicePixel, LayerPixel};
use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet};
@@ -27,18 +28,18 @@ use layers::scene::Scene;
use layout_traits::LayoutControlChan;
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind};
use msg::compositor_msg::{LayerProperties, ScrollPolicy};
use msg::constellation_msg::AnimationState;
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{AnimationState, Image, PixelFormat};
use msg::constellation_msg::{ConstellationChan, Key, KeyModifiers, KeyState, LoadData};
use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
use pipeline::CompositionPipeline;
use png;
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{ConstellationControlMsg, LayoutControlMsg};
use scrolling::ScrollingTimerProxy;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::mem as std_mem;
use std::rc::Rc;
use std::slice::bytes::copy_memory;
@@ -1521,7 +1522,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
/// for some reason. If CompositeTarget is Window or Png no image data is returned;
/// in the latter case the image is written directly to a file. If CompositeTarget
/// is WindowAndPng Ok(Some(png::Image)) is returned.
pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<png::Image>, ()> {
pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, ()> {

if !self.context.is_some() {
return Err(())
@@ -1573,13 +1574,19 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let rv = match target {
CompositeTarget::Window => None,
CompositeTarget::WindowAndPng => {
Some(self.draw_png(framebuffer_ids, texture_ids, width, height))
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
Some(Image {
width: img.width(),
height: img.height(),
format: PixelFormat::RGB8,
bytes: IpcSharedMemory::from_bytes(&*img),
})
}
CompositeTarget::PngFile => {
let mut img = self.draw_png(framebuffer_ids, texture_ids, width, height);
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
let path = opts::get().output_file.as_ref().unwrap();
let res = png::store_png(&mut img, &path);
assert!(res.is_ok(), format!("Error writing png: {}", res.unwrap_err()));
let mut file = File::create(path).unwrap();
DynamicImage::ImageRgb8(img).save(&mut file, ImageFormat::PNG).unwrap();
None
}
};
@@ -1596,12 +1603,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
Ok(rv)
}

fn draw_png(&self,
fn draw_img(&self,
framebuffer_ids: Vec<gl::GLuint>,
texture_ids: Vec<gl::GLuint>,
width: usize,
height: usize)
-> png::Image {
-> RgbImage {
let mut pixels = gl::read_pixels(0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
@@ -1622,11 +1629,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
copy_memory(&src_slice[..stride],
&mut pixels[dst_start .. dst_start + stride]);
}
png::Image {
width: width as u32,
height: height as u32,
pixels: png::PixelsByColorType::RGB8(pixels),
}
RgbImage::from_raw(width as u32, height as u32, pixels).unwrap()
}

fn composite_if_necessary(&mut self, reason: CompositingReason) {
@@ -13,8 +13,7 @@ use layers::platform::surface::{NativeDisplay, NativeSurface};
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerProperties};
use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId};
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use png;
use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState};
use profile_traits::mem;
use profile_traits::time;
use std::fmt::{Debug, Error, Formatter};
@@ -193,7 +192,7 @@ pub enum Msg {
/// Changes the cursor.
SetCursor(Cursor),
/// Composite to a PNG file and return the Image over a passed channel.
CreatePng(IpcSender<Option<png::Image>>),
CreatePng(IpcSender<Option<Image>>),
/// Informs the compositor that the paint task for the given pipeline has exited.
PaintTaskExited(PipelineId),
/// Alerts the compositor that the viewport has been constrained in some manner
@@ -33,14 +33,14 @@ extern crate euclid;
extern crate gfx;
extern crate gfx_traits;
extern crate gleam;
extern crate image;
extern crate ipc_channel;
extern crate layers;
extern crate layout_traits;
extern crate msg;
extern crate net_traits;
extern crate num;
extern crate offscreen_gl_context;
extern crate png;
extern crate script_traits;
extern crate style_traits;
extern crate time;
@@ -22,10 +22,6 @@ git = "https://github.com/servo/rust-azure"
[dependencies.layers]
git = "https://github.com/servo/rust-layers"

[dependencies.png]
git = "https://github.com/servo/rust-png"
features = [ "serde-serialization" ]

[dependencies.hyper]
version = "0.6"
features = [ "serde-serialization" ]
@@ -11,10 +11,9 @@ use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
use hyper::header::Headers;
use hyper::method::Method;
use ipc_channel::ipc::IpcSender;
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
use layers::geometry::DevicePixel;
use offscreen_gl_context::GLContextAttributes;
use png::Image;
use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
@@ -372,7 +371,24 @@ pub enum WebDriverCommandMsg {
LoadUrl(PipelineId, LoadData, IpcSender<LoadStatus>),
Refresh(PipelineId, IpcSender<LoadStatus>),
ScriptCommand(PipelineId, WebDriverScriptCommand),
TakeScreenshot(PipelineId, IpcSender<Option<Image>>)
TakeScreenshot(PipelineId, IpcSender<Option<Image>>),
}

#[derive(Deserialize, Eq, PartialEq, Serialize, HeapSizeOf)]
pub enum PixelFormat {
K8, // Luminance channel only
KA8, // Luminance + alpha
RGB8, // RGB, 8 bits per channel
RGBA8, // RGB + alpha, 8 bits per channel
}

#[derive(Deserialize, Serialize, HeapSizeOf)]
pub struct Image {
pub width: u32,
pub height: u32,
pub format: PixelFormat,
#[ignore_heap_size_of = "Defined in ipc-channel"]
pub bytes: IpcSharedMemory,
}

/// Similar to net::resource_task::LoadData
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(custom_derive, plugin)]
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros, plugins)]

extern crate app_units;
@@ -19,7 +19,6 @@ extern crate io_surface;
extern crate ipc_channel;
extern crate layers;
extern crate offscreen_gl_context;
extern crate png;
extern crate rustc_serialize;
extern crate serde;
extern crate style_traits;
@@ -19,10 +19,6 @@ path = "../devtools_traits"
[dependencies.plugins]
path = "../plugins"

[dependencies.png]
git = "https://github.com/servo/rust-png"
features = [ "serde-serialization" ]

[dependencies.hyper]
version = "0.6"
features = [ "serde-serialization" ]
@@ -21,7 +21,6 @@ extern crate hyper;
extern crate ipc_channel;
extern crate net_traits;
extern crate openssl;
extern crate png;
extern crate rustc_serialize;
extern crate time;
extern crate url;
@@ -7,10 +7,6 @@ authors = ["The Servo Project Developers"]
name = "net_traits"
path = "lib.rs"

[dependencies.png]
git = "https://github.com/servo/rust-png"
features = [ "serde-serialization" ]

[dependencies.util]
path = "../util"

@@ -37,6 +33,7 @@ path = "../plugins"
[dependencies]
log = "0.3"
euclid = "0.2"
image = "0.3.14"
regex = "0.1.33"
regex_macros = "0.1.19"
serde = "0.6"
@@ -3,32 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use ipc_channel::ipc::IpcSharedMemory;
use png;
use piston_image::{self, DynamicImage, GenericImage};
use stb_image::image as stb_image2;
use std::mem;
use util::mem::HeapSizeOf;
use util::vec::byte_swap;

pub use msg::constellation_msg::{Image, PixelFormat};

// FIXME: Images must not be copied every frame. Instead we should atomically
// reference count them.

#[derive(Deserialize, Serialize, HeapSizeOf)]
pub enum PixelFormat {
K8, // Luminance channel only
KA8, // Luminance + alpha
RGB8, // RGB, 8 bits per channel
RGBA8, // RGB + alpha, 8 bits per channel
}

#[derive(Deserialize, Serialize, HeapSizeOf)]
pub struct Image {
pub width: u32,
pub height: u32,
pub format: PixelFormat,
#[ignore_heap_size_of = "Defined in ipc-channel"]
pub bytes: IpcSharedMemory,
}

// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
fn byte_swap_and_premultiply(data: &mut [u8]) {
let length = data.len();
@@ -48,41 +31,10 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
return None;
}

if png::is_png(buffer) {
match png::load_png_from_memory(buffer) {
Ok(mut png_image) => {
let (bytes, format) = match png_image.pixels {
png::PixelsByColorType::K8(ref mut data) => {
(data, PixelFormat::K8)
}
png::PixelsByColorType::KA8(ref mut data) => {
(data, PixelFormat::KA8)
}
png::PixelsByColorType::RGB8(ref mut data) => {
byte_swap(data);
(data, PixelFormat::RGB8)
}
png::PixelsByColorType::RGBA8(ref mut data) => {
byte_swap_and_premultiply(data);
(data, PixelFormat::RGBA8)
}
};
if is_jpeg(buffer) {
// For JPEG images, we use stb_image because piston_image does not yet support progressive
// JPEG.

let bytes = mem::replace(bytes, Vec::new());
let bytes = IpcSharedMemory::from_bytes(&bytes[..]);
let image = Image {
width: png_image.width,
height: png_image.height,
format: format,
bytes: bytes,
};

Some(image)
}
Err(_err) => None,
}
} else {
// For non-png images, we use stb_image
// Can't remember why we do this. Maybe it's what cairo wants
static FORCE_DEPTH: usize = 4;

@@ -111,6 +63,26 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
None
}
}
} else {
match piston_image::load_from_memory(buffer) {
Ok(image) => {
let mut rgba = match image {
DynamicImage::ImageRgba8(rgba) => rgba,
image => image.to_rgba()
};
byte_swap_and_premultiply(&mut *rgba);
Some(Image {
width: rgba.width(),
height: rgba.height(),
format: PixelFormat::RGBA8,
bytes: IpcSharedMemory::from_bytes(&*rgba),
})
}
Err(e) => {
debug!("Image decoding error: {:?}", e);
None
}
}
}
}

@@ -120,3 +92,7 @@ fn is_gif(buffer: &[u8]) -> bool {
_ => false
}
}

fn is_jpeg(buffer: &[u8]) -> bool {
buffer.starts_with(&[0xff, 0xd8, 0xff])
}
@@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use image::base::Image;
use ipc_channel::ipc::{self, IpcSender};
use msg::constellation_msg::Image;
use std::sync::Arc;
use url::Url;
use util::mem::HeapSizeOf;
@@ -18,8 +18,8 @@ extern crate log;
extern crate euclid;
extern crate hyper;
extern crate ipc_channel;
extern crate image as piston_image;
extern crate msg;
extern crate png;
extern crate regex;
extern crate serde;
extern crate stb_image;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.