set (PNG_LIBRARIES png_bundled)
add_subdirectory (thirdparty/libpng EXCLUDE_FROM_ALL)
-include_directories (${PNG_INCLUDE_DIR})
-add_definitions (${PNG_DEFINITIONS})
if (MSVC)
add_subdirectory (thirdparty/getopt EXCLUDE_FROM_ALL)
common/trace_writer_model.cpp
common/trace_loader.cpp
common/trace_profiler.cpp
- common/image.cpp
- common/image_bmp.cpp
- common/image_pnm.cpp
- common/image_png.cpp
common/trace_option.cpp
common/${os}
)
add_subdirectory (dispatch)
add_subdirectory (helpers)
add_subdirectory (wrappers)
+add_subdirectory (image)
add_subdirectory (retrace)
target_link_libraries (apitrace
common
- ${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${SNAPPY_LIBRARIES}
${GETOPT_LIBRARIES}
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <math.h>
-
-#include <algorithm>
-
-#include "image.hpp"
-
-
-namespace image {
-
-
-double Image::compare(Image &ref)
-{
- if (width != ref.width ||
- height != ref.height ||
- channels < 3 ||
- ref.channels < 3) {
- return 0.0;
- }
-
- // Ignore missing alpha when comparing RGB w/ RGBA, but enforce an equal
- // number of channels otherwise.
- unsigned minChannels = std::min(channels, ref.channels);
- if (channels != ref.channels && minChannels < 3) {
- return 0.0;
- }
-
- const unsigned char *pSrc = start();
- const unsigned char *pRef = ref.start();
-
- unsigned long long error = 0;
- for (unsigned y = 0; y < height; ++y) {
- for (unsigned x = 0; x < width; ++x) {
- // FIXME: Ignore alpha channel until we are able to pick a visual
- // that matches the traces
- for (unsigned c = 0; c < minChannels; ++c) {
- int delta = pSrc[x*channels + c] - pRef[x*ref.channels + c];
- error += delta*delta;
- }
- }
-
- pSrc += stride();
- pRef += ref.stride();
- }
-
- double numerator = error*2 + 1;
- double denominator = height*width*minChannels*255ULL*255ULL*2;
- double quotient = numerator/denominator;
-
- // Precision in bits
- double precision = -log(quotient)/log(2.0);
-
- return precision;
-}
-
-
-} /* namespace image */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2008-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-/*
- * Image I/O.
- */
-
-#ifndef _IMAGE_HPP_
-#define _IMAGE_HPP_
-
-
-#include <fstream>
-
-
-namespace image {
-
-
-class Image {
-public:
- unsigned width;
- unsigned height;
- unsigned channels;
-
- // Flipped vertically or not
- bool flipped;
-
- // Pixels in RGBA format
- unsigned char *pixels;
-
- inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) :
- width(w),
- height(h),
- channels(c),
- flipped(f),
- pixels(new unsigned char[h*w*c])
- {}
-
- inline ~Image() {
- delete [] pixels;
- }
-
- inline unsigned char *start(void) {
- return flipped ? pixels + (height - 1)*width*channels : pixels;
- }
-
- inline const unsigned char *start(void) const {
- return flipped ? pixels + (height - 1)*width*channels : pixels;
- }
-
- inline unsigned char *end(void) {
- return flipped ? pixels - width*channels : pixels + height*width*channels;
- }
-
- inline const unsigned char *end(void) const {
- return flipped ? pixels - width*channels : pixels + height*width*channels;
- }
-
- inline signed stride(void) const {
- return flipped ? -(signed)(width*channels) : width*channels;
- }
-
- bool writeBMP(const char *filename) const;
-
- void writePNM(std::ostream &os, const char *comment = NULL) const;
-
- inline bool writePNM(const char *filename, const char *comment = NULL) const {
- std::ofstream os(filename, std::ofstream::binary);
- if (!os) {
- return false;
- }
- writePNM(os, comment);
- return true;
- }
-
- bool
- writePNG(std::ostream &os) const;
-
- inline bool
- writePNG(const char *filename) const {
- std::ofstream os(filename, std::ofstream::binary);
- if (!os) {
- return false;
- }
- return writePNG(os);
- }
-
- double compare(Image &ref);
-};
-
-
-Image *
-readPNG(const char *filename);
-
-const char *
-readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height);
-
-
-} /* namespace image */
-
-
-#endif /* _IMAGE_HPP_ */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "image.hpp"
-
-
-namespace image {
-
-
-#pragma pack(push,2)
-struct FileHeader {
- uint16_t bfType;
- uint32_t bfSize;
- uint16_t bfReserved1;
- uint16_t bfReserved2;
- uint32_t bfOffBits;
-};
-#pragma pack(pop)
-
-struct InfoHeader {
- uint32_t biSize;
- int32_t biWidth;
- int32_t biHeight;
- uint16_t biPlanes;
- uint16_t biBitCount;
- uint32_t biCompression;
- uint32_t biSizeImage;
- int32_t biXPelsPerMeter;
- int32_t biYPelsPerMeter;
- uint32_t biClrUsed;
- uint32_t biClrImportant;
-};
-
-struct Pixel {
- uint8_t rgbBlue;
- uint8_t rgbGreen;
- uint8_t rgbRed;
- uint8_t rgbAlpha;
-};
-
-
-bool
-Image::writeBMP(const char *filename) const {
- assert(channels == 4);
-
- struct FileHeader bmfh;
- struct InfoHeader bmih;
- unsigned x, y;
-
- bmfh.bfType = 0x4d42;
- bmfh.bfSize = 14 + 40 + height*width*4;
- bmfh.bfReserved1 = 0;
- bmfh.bfReserved2 = 0;
- bmfh.bfOffBits = 14 + 40;
-
- bmih.biSize = 40;
- bmih.biWidth = width;
- bmih.biHeight = height;
- bmih.biPlanes = 1;
- bmih.biBitCount = 32;
- bmih.biCompression = 0;
- bmih.biSizeImage = height*width*4;
- bmih.biXPelsPerMeter = 0;
- bmih.biYPelsPerMeter = 0;
- bmih.biClrUsed = 0;
- bmih.biClrImportant = 0;
-
- std::ofstream stream(filename, std::ofstream::binary);
-
- if (!stream) {
- return false;
- }
-
- stream.write((const char *)&bmfh, 14);
- stream.write((const char *)&bmih, 40);
-
- unsigned stride = width*4;
-
- if (flipped) {
- for (y = 0; y < height; ++y) {
- const unsigned char *ptr = pixels + y * stride;
- for (x = 0; x < width; ++x) {
- struct Pixel pixel;
- pixel.rgbRed = ptr[x*4 + 0];
- pixel.rgbGreen = ptr[x*4 + 1];
- pixel.rgbBlue = ptr[x*4 + 2];
- pixel.rgbAlpha = ptr[x*4 + 3];
- stream.write((const char *)&pixel, 4);
- }
- }
- } else {
- y = height;
- while (y--) {
- const unsigned char *ptr = pixels + y * stride;
- for (x = 0; x < width; ++x) {
- struct Pixel pixel;
- pixel.rgbRed = ptr[x*4 + 0];
- pixel.rgbGreen = ptr[x*4 + 1];
- pixel.rgbBlue = ptr[x*4 + 2];
- pixel.rgbAlpha = ptr[x*4 + 3];
- stream.write((const char *)&pixel, 4);
- }
- }
- }
-
- stream.close();
-
- return true;
-}
-
-
-} /* namespace image */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include <zlib.h>
-#include <png.h>
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <fstream>
-
-#include "image.hpp"
-
-
-namespace image {
-
-
-static const int png_compression_level = Z_BEST_SPEED;
-
-
-static void
-pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- std::ostream *os = (std::ostream *) png_get_io_ptr(png_ptr);
- os->write((const char *)data, length);
-}
-
-bool
-Image::writePNG(std::ostream &os) const
-{
- png_structp png_ptr;
- png_infop info_ptr;
- int color_type;
-
- switch (channels) {
- case 4:
- color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- break;
- case 3:
- color_type = PNG_COLOR_TYPE_RGB;
- break;
- case 2:
- color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
- break;
- case 1:
- color_type = PNG_COLOR_TYPE_GRAY;
- break;
- default:
- assert(0);
- goto no_png;
- }
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr)
- goto no_png;
-
- info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr) {
- png_destroy_write_struct(&png_ptr, NULL);
- goto no_png;
- }
-
- if (setjmp(png_jmpbuf(png_ptr))) {
- png_destroy_write_struct(&png_ptr, &info_ptr);
- goto no_png;
- }
-
- png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL);
-
- png_set_IHDR(png_ptr, info_ptr, width, height, 8,
- color_type, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- png_set_compression_level(png_ptr, png_compression_level);
-
- png_write_info(png_ptr, info_ptr);
-
- if (!flipped) {
- for (unsigned y = 0; y < height; ++y) {
- png_bytep row = (png_bytep)(pixels + y*width*channels);
- png_write_rows(png_ptr, &row, 1);
- }
- } else {
- unsigned y = height;
- while (y--) {
- png_bytep row = (png_bytep)(pixels + y*width*channels);
- png_write_rows(png_ptr, &row, 1);
- }
- }
-
- png_write_end(png_ptr, info_ptr);
- png_destroy_write_struct(&png_ptr, &info_ptr);
-
- return true;
-
-no_png:
- return false;
-}
-
-
-Image *
-readPNG(const char *filename)
-{
- FILE *fp;
- png_structp png_ptr;
- png_infop info_ptr;
- png_infop end_info;
- Image *image;
-
- fp = fopen(filename, "rb");
- if (!fp)
- goto no_fp;
-
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr)
- goto no_png;
-
- info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr) {
- png_destroy_read_struct(&png_ptr, NULL, NULL);
- goto no_png;
- }
-
- end_info = png_create_info_struct(png_ptr);
- if (!end_info) {
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- goto no_png;
- }
-
- if (setjmp(png_jmpbuf(png_ptr))) {
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
- goto no_png;
- }
-
- png_init_io(png_ptr, fp);
-
- png_read_info(png_ptr, info_ptr);
-
- png_uint_32 width, height;
- int bit_depth, color_type, interlace_type, compression_type, filter_method;
-
- png_get_IHDR(png_ptr, info_ptr,
- &width, &height,
- &bit_depth, &color_type, &interlace_type,
- &compression_type, &filter_method);
-
- image = new Image(width, height);
- if (!image)
- goto no_image;
-
- /* Convert to RGBA8 */
- if (color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_palette_to_rgb(png_ptr);
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
- png_set_expand_gray_1_2_4_to_8(png_ptr);
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
- png_set_tRNS_to_alpha(png_ptr);
- if (bit_depth == 16)
- png_set_strip_16(png_ptr);
-
- for (unsigned y = 0; y < height; ++y) {
- png_bytep row = (png_bytep)(image->pixels + y*width*4);
- png_read_row(png_ptr, row, NULL);
- }
-
- png_read_end(png_ptr, info_ptr);
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
- fclose(fp);
- return image;
-
-no_image:
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-no_png:
- fclose(fp);
-no_fp:
- return NULL;
-}
-
-
-
-} /* namespace image */
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "image.hpp"
-
-
-namespace image {
-
-/**
- * http://en.wikipedia.org/wiki/Netpbm_format
- * http://netpbm.sourceforge.net/doc/ppm.html
- */
-void
-Image::writePNM(std::ostream &os, const char *comment) const {
- assert(channels == 1 || channels >= 3);
-
- os << (channels == 1 ? "P5" : "P6") << "\n";
- if (comment) {
- os << "#" << comment << "\n";
- }
- os << width << " " << height << "\n";
- os << "255" << "\n";
-
- const unsigned char *row;
-
- if (channels == 1 || channels == 3) {
- for (row = start(); row != end(); row += stride()) {
- os.write((const char *)row, width*channels);
- }
- } else {
- unsigned char *tmp = new unsigned char[width*3];
- if (channels == 4) {
- for (row = start(); row != end(); row += stride()) {
- const uint32_t *src = (const uint32_t *)row;
- uint32_t *dst = (uint32_t *)tmp;
- unsigned x;
- for (x = 0; x + 4 <= width; x += 4) {
- /*
- * It's much faster to access dwords than bytes.
- *
- * FIXME: Big-endian version.
- */
-
- uint32_t rgba0 = *src++ & 0xffffff;
- uint32_t rgba1 = *src++ & 0xffffff;
- uint32_t rgba2 = *src++ & 0xffffff;
- uint32_t rgba3 = *src++ & 0xffffff;
- uint32_t rgb0 = rgba0
- | (rgba1 << 24);
- uint32_t rgb1 = (rgba1 >> 8)
- | (rgba2 << 16);
- uint32_t rgb2 = (rgba2 >> 16)
- | (rgba3 << 8);
- *dst++ = rgb0;
- *dst++ = rgb1;
- *dst++ = rgb2;
- }
- for (; x < width; ++x) {
- tmp[x*3 + 0] = row[x*4 + 0];
- tmp[x*3 + 1] = row[x*4 + 1];
- tmp[x*3 + 2] = row[x*4 + 2];
- }
- os.write((const char *)tmp, width*3);
- }
- } else if (channels == 2) {
- for (row = start(); row != end(); row += stride()) {
- const unsigned char *src = row;
- unsigned char *dst = tmp;
- for (unsigned x = 0; x < width; ++x) {
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = 0;
- }
- os.write((const char *)tmp, width*3);
- }
- } else {
- assert(0);
- }
- delete [] tmp;
- }
-}
-
-const char *
-readPNMHeader(const char *buffer, size_t bufferSize, unsigned *channels, unsigned *width, unsigned *height)
-{
- *channels = 0;
- *width = 0;
- *height = 0;
-
- const char *currentBuffer = buffer;
- const char *nextBuffer;
-
- // parse number of channels
- int scannedChannels = sscanf(currentBuffer, "P%d\n", channels);
- if (scannedChannels != 1) { // validate scanning of channels
- // invalid channel line
- return buffer;
- }
- // convert channel token to number of channels
- *channels = (*channels == 5) ? 1 : 3;
-
- // advance past channel line
- nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
- bufferSize -= nextBuffer - currentBuffer;
- currentBuffer = nextBuffer;
-
- // skip over optional comment
- if (*currentBuffer == '#') {
- // advance past comment line
- nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
- bufferSize -= nextBuffer - currentBuffer;
- currentBuffer = nextBuffer;
- }
-
- // parse dimensions of image
- int scannedDimensions = sscanf(currentBuffer, "%d %d\n", width, height);
- if (scannedDimensions != 2) { // validate scanning of dimensions
- // invalid dimension line
- return buffer;
- }
-
- // advance past dimension line
- nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
- bufferSize -= nextBuffer - currentBuffer;
- currentBuffer = nextBuffer;
-
- // skip over "255\n" at end of header
- nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
-
- // return start of image data
- return nextBuffer;
-}
-
-} /* namespace image */
#add_app_icon(qapitrace_SRCS ../icons/hi*-qapitrace.png)
link_directories(${LINK_DIRECTORIES} ${QJSON_LIBRARY_DIRS})
-include_directories(${QT_INCLUDES} ${QJSON_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..)
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}
+ ${QJSON_INCLUDE_DIR}
+ ${QT_INCLUDES}
+)
if (WIN32)
# Use Windows subsystem (i.e., no console).
add_executable(qapitrace ${qapitrace_SUBSYSTEM} ${qapitrace_SRCS} ${qapitrace_UIS_H})
target_link_libraries (qapitrace
+ image
common
- ${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${SNAPPY_LIBRARIES}
${QJSON_LIBRARIES}
#include "apitracecall.h"
#include "thumbnail.h"
-#include "image.hpp"
+#include "image/image.hpp"
#include "trace_profiler.hpp"
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <math.h>
+
+#include <algorithm>
+
+#include "image.hpp"
+
+
+namespace image {
+
+
+double Image::compare(Image &ref)
+{
+ if (width != ref.width ||
+ height != ref.height ||
+ channels < 3 ||
+ ref.channels < 3) {
+ return 0.0;
+ }
+
+ // Ignore missing alpha when comparing RGB w/ RGBA, but enforce an equal
+ // number of channels otherwise.
+ unsigned minChannels = std::min(channels, ref.channels);
+ if (channels != ref.channels && minChannels < 3) {
+ return 0.0;
+ }
+
+ const unsigned char *pSrc = start();
+ const unsigned char *pRef = ref.start();
+
+ unsigned long long error = 0;
+ for (unsigned y = 0; y < height; ++y) {
+ for (unsigned x = 0; x < width; ++x) {
+ // FIXME: Ignore alpha channel until we are able to pick a visual
+ // that matches the traces
+ for (unsigned c = 0; c < minChannels; ++c) {
+ int delta = pSrc[x*channels + c] - pRef[x*ref.channels + c];
+ error += delta*delta;
+ }
+ }
+
+ pSrc += stride();
+ pRef += ref.stride();
+ }
+
+ double numerator = error*2 + 1;
+ double denominator = height*width*minChannels*255ULL*255ULL*2;
+ double quotient = numerator/denominator;
+
+ // Precision in bits
+ double precision = -log(quotient)/log(2.0);
+
+ return precision;
+}
+
+
+} /* namespace image */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Image I/O.
+ */
+
+#ifndef _IMAGE_HPP_
+#define _IMAGE_HPP_
+
+
+#include <fstream>
+
+
+namespace image {
+
+
+class Image {
+public:
+ unsigned width;
+ unsigned height;
+ unsigned channels;
+
+ // Flipped vertically or not
+ bool flipped;
+
+ // Pixels in RGBA format
+ unsigned char *pixels;
+
+ inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) :
+ width(w),
+ height(h),
+ channels(c),
+ flipped(f),
+ pixels(new unsigned char[h*w*c])
+ {}
+
+ inline ~Image() {
+ delete [] pixels;
+ }
+
+ inline unsigned char *start(void) {
+ return flipped ? pixels + (height - 1)*width*channels : pixels;
+ }
+
+ inline const unsigned char *start(void) const {
+ return flipped ? pixels + (height - 1)*width*channels : pixels;
+ }
+
+ inline unsigned char *end(void) {
+ return flipped ? pixels - width*channels : pixels + height*width*channels;
+ }
+
+ inline const unsigned char *end(void) const {
+ return flipped ? pixels - width*channels : pixels + height*width*channels;
+ }
+
+ inline signed stride(void) const {
+ return flipped ? -(signed)(width*channels) : width*channels;
+ }
+
+ bool writeBMP(const char *filename) const;
+
+ void writePNM(std::ostream &os, const char *comment = NULL) const;
+
+ inline bool writePNM(const char *filename, const char *comment = NULL) const {
+ std::ofstream os(filename, std::ofstream::binary);
+ if (!os) {
+ return false;
+ }
+ writePNM(os, comment);
+ return true;
+ }
+
+ bool
+ writePNG(std::ostream &os) const;
+
+ inline bool
+ writePNG(const char *filename) const {
+ std::ofstream os(filename, std::ofstream::binary);
+ if (!os) {
+ return false;
+ }
+ return writePNG(os);
+ }
+
+ double compare(Image &ref);
+};
+
+
+Image *
+readPNG(const char *filename);
+
+const char *
+readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height);
+
+
+} /* namespace image */
+
+
+#endif /* _IMAGE_HPP_ */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "image.hpp"
+
+
+namespace image {
+
+
+#pragma pack(push,2)
+struct FileHeader {
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+};
+#pragma pack(pop)
+
+struct InfoHeader {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+};
+
+struct Pixel {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ uint8_t rgbAlpha;
+};
+
+
+bool
+Image::writeBMP(const char *filename) const {
+ assert(channels == 4);
+
+ struct FileHeader bmfh;
+ struct InfoHeader bmih;
+ unsigned x, y;
+
+ bmfh.bfType = 0x4d42;
+ bmfh.bfSize = 14 + 40 + height*width*4;
+ bmfh.bfReserved1 = 0;
+ bmfh.bfReserved2 = 0;
+ bmfh.bfOffBits = 14 + 40;
+
+ bmih.biSize = 40;
+ bmih.biWidth = width;
+ bmih.biHeight = height;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = 0;
+ bmih.biSizeImage = height*width*4;
+ bmih.biXPelsPerMeter = 0;
+ bmih.biYPelsPerMeter = 0;
+ bmih.biClrUsed = 0;
+ bmih.biClrImportant = 0;
+
+ std::ofstream stream(filename, std::ofstream::binary);
+
+ if (!stream) {
+ return false;
+ }
+
+ stream.write((const char *)&bmfh, 14);
+ stream.write((const char *)&bmih, 40);
+
+ unsigned stride = width*4;
+
+ if (flipped) {
+ for (y = 0; y < height; ++y) {
+ const unsigned char *ptr = pixels + y * stride;
+ for (x = 0; x < width; ++x) {
+ struct Pixel pixel;
+ pixel.rgbRed = ptr[x*4 + 0];
+ pixel.rgbGreen = ptr[x*4 + 1];
+ pixel.rgbBlue = ptr[x*4 + 2];
+ pixel.rgbAlpha = ptr[x*4 + 3];
+ stream.write((const char *)&pixel, 4);
+ }
+ }
+ } else {
+ y = height;
+ while (y--) {
+ const unsigned char *ptr = pixels + y * stride;
+ for (x = 0; x < width; ++x) {
+ struct Pixel pixel;
+ pixel.rgbRed = ptr[x*4 + 0];
+ pixel.rgbGreen = ptr[x*4 + 1];
+ pixel.rgbBlue = ptr[x*4 + 2];
+ pixel.rgbAlpha = ptr[x*4 + 3];
+ stream.write((const char *)&pixel, 4);
+ }
+ }
+ }
+
+ stream.close();
+
+ return true;
+}
+
+
+} /* namespace image */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <zlib.h>
+#include <png.h>
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <fstream>
+
+#include "image.hpp"
+
+
+namespace image {
+
+
+static const int png_compression_level = Z_BEST_SPEED;
+
+
+static void
+pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ std::ostream *os = (std::ostream *) png_get_io_ptr(png_ptr);
+ os->write((const char *)data, length);
+}
+
+bool
+Image::writePNG(std::ostream &os) const
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ int color_type;
+
+ switch (channels) {
+ case 4:
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case 3:
+ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case 2:
+ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ break;
+ case 1:
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ default:
+ assert(0);
+ goto no_png;
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ goto no_png;
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr, NULL);
+ goto no_png;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ goto no_png;
+ }
+
+ png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL);
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+ color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_set_compression_level(png_ptr, png_compression_level);
+
+ png_write_info(png_ptr, info_ptr);
+
+ if (!flipped) {
+ for (unsigned y = 0; y < height; ++y) {
+ png_bytep row = (png_bytep)(pixels + y*width*channels);
+ png_write_rows(png_ptr, &row, 1);
+ }
+ } else {
+ unsigned y = height;
+ while (y--) {
+ png_bytep row = (png_bytep)(pixels + y*width*channels);
+ png_write_rows(png_ptr, &row, 1);
+ }
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return true;
+
+no_png:
+ return false;
+}
+
+
+Image *
+readPNG(const char *filename)
+{
+ FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_infop end_info;
+ Image *image;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ goto no_fp;
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ goto no_png;
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ goto no_png;
+ }
+
+ end_info = png_create_info_struct(png_ptr);
+ if (!end_info) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ goto no_png;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ goto no_png;
+ }
+
+ png_init_io(png_ptr, fp);
+
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type, compression_type, filter_method;
+
+ png_get_IHDR(png_ptr, info_ptr,
+ &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_method);
+
+ image = new Image(width, height);
+ if (!image)
+ goto no_image;
+
+ /* Convert to RGBA8 */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+ for (unsigned y = 0; y < height; ++y) {
+ png_bytep row = (png_bytep)(image->pixels + y*width*4);
+ png_read_row(png_ptr, row, NULL);
+ }
+
+ png_read_end(png_ptr, info_ptr);
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ fclose(fp);
+ return image;
+
+no_image:
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+no_png:
+ fclose(fp);
+no_fp:
+ return NULL;
+}
+
+
+
+} /* namespace image */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "image.hpp"
+
+
+namespace image {
+
+/**
+ * http://en.wikipedia.org/wiki/Netpbm_format
+ * http://netpbm.sourceforge.net/doc/ppm.html
+ */
+void
+Image::writePNM(std::ostream &os, const char *comment) const {
+ assert(channels == 1 || channels >= 3);
+
+ os << (channels == 1 ? "P5" : "P6") << "\n";
+ if (comment) {
+ os << "#" << comment << "\n";
+ }
+ os << width << " " << height << "\n";
+ os << "255" << "\n";
+
+ const unsigned char *row;
+
+ if (channels == 1 || channels == 3) {
+ for (row = start(); row != end(); row += stride()) {
+ os.write((const char *)row, width*channels);
+ }
+ } else {
+ unsigned char *tmp = new unsigned char[width*3];
+ if (channels == 4) {
+ for (row = start(); row != end(); row += stride()) {
+ const uint32_t *src = (const uint32_t *)row;
+ uint32_t *dst = (uint32_t *)tmp;
+ unsigned x;
+ for (x = 0; x + 4 <= width; x += 4) {
+ /*
+ * It's much faster to access dwords than bytes.
+ *
+ * FIXME: Big-endian version.
+ */
+
+ uint32_t rgba0 = *src++ & 0xffffff;
+ uint32_t rgba1 = *src++ & 0xffffff;
+ uint32_t rgba2 = *src++ & 0xffffff;
+ uint32_t rgba3 = *src++ & 0xffffff;
+ uint32_t rgb0 = rgba0
+ | (rgba1 << 24);
+ uint32_t rgb1 = (rgba1 >> 8)
+ | (rgba2 << 16);
+ uint32_t rgb2 = (rgba2 >> 16)
+ | (rgba3 << 8);
+ *dst++ = rgb0;
+ *dst++ = rgb1;
+ *dst++ = rgb2;
+ }
+ for (; x < width; ++x) {
+ tmp[x*3 + 0] = row[x*4 + 0];
+ tmp[x*3 + 1] = row[x*4 + 1];
+ tmp[x*3 + 2] = row[x*4 + 2];
+ }
+ os.write((const char *)tmp, width*3);
+ }
+ } else if (channels == 2) {
+ for (row = start(); row != end(); row += stride()) {
+ const unsigned char *src = row;
+ unsigned char *dst = tmp;
+ for (unsigned x = 0; x < width; ++x) {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = 0;
+ }
+ os.write((const char *)tmp, width*3);
+ }
+ } else {
+ assert(0);
+ }
+ delete [] tmp;
+ }
+}
+
+const char *
+readPNMHeader(const char *buffer, size_t bufferSize, unsigned *channels, unsigned *width, unsigned *height)
+{
+ *channels = 0;
+ *width = 0;
+ *height = 0;
+
+ const char *currentBuffer = buffer;
+ const char *nextBuffer;
+
+ // parse number of channels
+ int scannedChannels = sscanf(currentBuffer, "P%d\n", channels);
+ if (scannedChannels != 1) { // validate scanning of channels
+ // invalid channel line
+ return buffer;
+ }
+ // convert channel token to number of channels
+ *channels = (*channels == 5) ? 1 : 3;
+
+ // advance past channel line
+ nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+ bufferSize -= nextBuffer - currentBuffer;
+ currentBuffer = nextBuffer;
+
+ // skip over optional comment
+ if (*currentBuffer == '#') {
+ // advance past comment line
+ nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+ bufferSize -= nextBuffer - currentBuffer;
+ currentBuffer = nextBuffer;
+ }
+
+ // parse dimensions of image
+ int scannedDimensions = sscanf(currentBuffer, "%d %d\n", width, height);
+ if (scannedDimensions != 2) { // validate scanning of dimensions
+ // invalid dimension line
+ return buffer;
+ }
+
+ // advance past dimension line
+ nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+ bufferSize -= nextBuffer - currentBuffer;
+ currentBuffer = nextBuffer;
+
+ // skip over "255\n" at end of header
+ nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+
+ // return start of image data
+ return nextBuffer;
+}
+
+} /* namespace image */
${CMAKE_SOURCE_DIR}/helpers
${CMAKE_BINARY_DIR}/dispatch
${CMAKE_SOURCE_DIR}/dispatch
+ ${CMAKE_SOURCE_DIR}/image
)
add_definitions (-DRETRACE)
json.cpp
)
target_link_libraries (retrace_common
+ image
common
- ${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${SNAPPY_LIBRARIES}
${GETOPT_LIBRARIES}