Working image duplicate removal.

This commit is contained in:
John McNamara 2019-12-26 15:52:01 +00:00
parent a4f9e5bad0
commit 1290420818
15 changed files with 351 additions and 34 deletions

1
.indent.pro vendored
View File

@ -96,6 +96,7 @@
-T lxw_drawing
-T lxw_drawing_coords
-T lxw_drawing_object
-T lxw_drawing_rel_id
-T lxw_error
-T lxw_fill
-T lxw_font

View File

@ -97,7 +97,7 @@ typedef struct lxw_chartsheet_name {
/* Struct to represent an image MD5/ID pair. */
typedef struct lxw_image_md5 {
uint32_t id;
unsigned char md5[LXW_MD5_SIZE];
char *md5;
RB_ENTRY (lxw_image_md5) tree_pointers;
} lxw_image_md5;

View File

@ -62,7 +62,7 @@
#define LXW_HEADER_FOOTER_MAX 255
#define LXW_MAX_NUMBER_URLS 65530
#define LXW_PANE_NAME_LENGTH 12 /* bottomRight + 1 */
#define LXW_IMAGE_BUFFER_SIZE 10
#define LXW_IMAGE_BUFFER_SIZE 1024
/* The Excel 2007 specification says that the maximum number of page
* breaks is 1026. However, in practice it is actually 1023. */
@ -226,6 +226,7 @@ enum pane_types {
/* Define the tree.h RB structs for the red-black head types. */
RB_HEAD(lxw_table_cells, lxw_cell);
RB_HEAD(lxw_drawing_rel_ids, lxw_drawing_rel_id);
/* Define a RB_TREE struct manually to add extra members. */
struct lxw_table_rows {
@ -258,6 +259,17 @@ struct lxw_table_rows {
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_cell{int unused;}
#define LXW_RB_GENERATE_DRAWING_REL_IDS(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
RB_GENERATE_INSERT(name, type, field, cmp, static) \
RB_GENERATE_REMOVE(name, type, field, static) \
RB_GENERATE_FIND(name, type, field, cmp, static) \
RB_GENERATE_NEXT(name, type, field, static) \
RB_GENERATE_MINMAX(name, type, field, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_drawing_rel_ids{int unused;}
STAILQ_HEAD(lxw_merged_ranges, lxw_merged_range);
STAILQ_HEAD(lxw_selections, lxw_selection);
STAILQ_HEAD(lxw_data_validations, lxw_data_val_obj);
@ -641,7 +653,7 @@ typedef struct lxw_object_properties {
double y_dpi;
lxw_chart *chart;
uint8_t is_duplicate;
unsigned char md5[LXW_MD5_SIZE];
char *md5;
STAILQ_ENTRY (lxw_object_properties) list_pointers;
} lxw_object_properties;
@ -777,6 +789,7 @@ typedef struct lxw_worksheet {
struct lxw_data_validations *data_validations;
struct lxw_image_props *image_props;
struct lxw_chart_props *chart_data;
struct lxw_drawing_rel_ids *drawing_rel_ids;
lxw_row_t dim_rowmin;
lxw_row_t dim_rowmax;
@ -950,6 +963,14 @@ typedef struct lxw_cell {
RB_ENTRY (lxw_cell) tree_pointers;
} lxw_cell;
/* Struct to represent a drawing Target/ID pair. */
typedef struct lxw_drawing_rel_id {
uint32_t id;
char *target;
RB_ENTRY (lxw_drawing_rel_id) tree_pointers;
} lxw_drawing_rel_id;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {

View File

@ -56,7 +56,7 @@ _chartsheet_name_cmp(lxw_chartsheet_name *name1, lxw_chartsheet_name *name2)
STATIC int
_image_md5_cmp(lxw_image_md5 *tuple1, lxw_image_md5 *tuple2)
{
return memcmp(tuple1->md5, tuple2->md5, LXW_MD5_SIZE);
return strcmp(tuple1->md5, tuple2->md5);
}
/*
@ -223,6 +223,7 @@ lxw_workbook_free(lxw_workbook *workbook)
next_image_md5 =
RB_NEXT(lxw_image_md5s, workbook->image_md5, image_md5);
RB_REMOVE(lxw_image_md5s, workbook->image_md5s, image_md5);
free(image_md5->md5);
free(image_md5);
}
@ -925,7 +926,7 @@ _prepare_drawings(lxw_workbook *self)
uint8_t is_chartsheet;
lxw_image_md5 tmp_image_md5;
lxw_image_md5 *new_image_md5 = NULL;
lxw_image_md5 *found;
lxw_image_md5 *found_duplicate_image = NULL;
STAILQ_FOREACH(sheet, self->sheets, list_pointers) {
if (sheet->is_chartsheet) {
@ -954,12 +955,16 @@ _prepare_drawings(lxw_workbook *self)
if (object_props->image_type == LXW_IMAGE_BMP)
self->has_bmp = LXW_TRUE;
memcpy(tmp_image_md5.md5, object_props->md5, LXW_MD5_SIZE);
/* Check for duplicate images and only store the first instance. */
if (object_props->md5) {
tmp_image_md5.md5 = object_props->md5;
found_duplicate_image = RB_FIND(lxw_image_md5s,
self->image_md5s,
&tmp_image_md5);
}
found = RB_FIND(lxw_image_md5s, self->image_md5s, &tmp_image_md5);
if (found) {
ref_id = found->id;
if (found_duplicate_image) {
ref_id = found_duplicate_image->id;
object_props->is_duplicate = LXW_TRUE;
}
else {
@ -969,10 +974,9 @@ _prepare_drawings(lxw_workbook *self)
#ifndef USE_NO_MD5
new_image_md5 = calloc(1, sizeof(lxw_image_md5));
#endif
if (new_image_md5) {
if (new_image_md5 && object_props->md5) {
new_image_md5->id = ref_id;
memcpy(new_image_md5->md5, object_props->md5,
LXW_MD5_SIZE);
new_image_md5->md5 = lxw_strdup(object_props->md5);
RB_INSERT(lxw_image_md5s, self->image_md5s,
new_image_md5);

View File

@ -26,10 +26,14 @@
STATIC void _worksheet_write_rows(lxw_worksheet *self);
STATIC int _row_cmp(lxw_row *row1, lxw_row *row2);
STATIC int _cell_cmp(lxw_cell *cell1, lxw_cell *cell2);
STATIC int _drawing_rel_id_cmp(lxw_drawing_rel_id *tuple1,
lxw_drawing_rel_id *tuple2);
#ifndef __clang_analyzer__
LXW_RB_GENERATE_ROW(lxw_table_rows, lxw_row, tree_pointers, _row_cmp);
LXW_RB_GENERATE_CELL(lxw_table_cells, lxw_cell, tree_pointers, _cell_cmp);
LXW_RB_GENERATE_DRAWING_REL_IDS(lxw_drawing_rel_ids, lxw_drawing_rel_id,
tree_pointers, _drawing_rel_id_cmp);
#endif
/*****************************************************************************
@ -155,6 +159,11 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
worksheet->file = worksheet->optimize_tmpfile;
}
worksheet->drawing_rel_ids =
calloc(1, sizeof(struct lxw_drawing_rel_ids));
GOTO_LABEL_ON_MEM_ERROR(worksheet->drawing_rel_ids, mem_error);
RB_INIT(worksheet->drawing_rel_ids);
/* Initialize the worksheet dimensions. */
worksheet->dim_rowmax = 0;
worksheet->dim_colmax = 0;
@ -276,6 +285,7 @@ _free_object_properties(lxw_object_properties *object_property)
free(object_property->url);
free(object_property->tip);
free(object_property->image_buffer);
free(object_property->md5);
free(object_property);
}
@ -313,6 +323,8 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
lxw_selection *selection;
lxw_data_val_obj *data_validation;
lxw_rel_tuple *relationship;
struct lxw_drawing_rel_id *drawing_rel_id;
struct lxw_drawing_rel_id *next_drawing_rel_id;
if (!worksheet)
return;
@ -432,6 +444,23 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
}
free(worksheet->drawing_links);
if (worksheet->drawing_rel_ids) {
for (drawing_rel_id =
RB_MIN(lxw_drawing_rel_ids, worksheet->drawing_rel_ids);
drawing_rel_id; drawing_rel_id = next_drawing_rel_id) {
next_drawing_rel_id =
RB_NEXT(lxw_drawing_rel_ids, worksheet->drawing_rel_id,
drawing_rel_id);
RB_REMOVE(lxw_drawing_rel_ids, worksheet->drawing_rel_ids,
drawing_rel_id);
free(drawing_rel_id->target);
free(drawing_rel_id);
}
free(worksheet->drawing_rel_ids);
}
if (worksheet->array) {
for (col = 0; col < LXW_COL_MAX; col++) {
_free_cell(worksheet->array[col]);
@ -862,19 +891,72 @@ _cell_cmp(lxw_cell *cell1, lxw_cell *cell2)
return 0;
}
STATIC int
_drawing_rel_id_cmp(lxw_drawing_rel_id *rel_id1, lxw_drawing_rel_id *rel_id2)
{
return strcmp(rel_id1->target, rel_id2->target);
}
/*
* Get the index used to address a drawing rel link.
*/
STATIC uint32_t
_get_drawing_rel_index(lxw_worksheet *self, char *target)
{
lxw_drawing_rel_id tmp_drawing_rel_id;
lxw_drawing_rel_id *found_duplicate_target = NULL;
lxw_drawing_rel_id *new_drawing_rel_id = NULL;
if (!target) {
self->drawing_rel_id++;
return self->drawing_rel_id;
if (target) {
tmp_drawing_rel_id.target = target;
found_duplicate_target = RB_FIND(lxw_drawing_rel_ids,
self->drawing_rel_ids,
&tmp_drawing_rel_id);
}
return 0;
if (found_duplicate_target) {
return found_duplicate_target->id;
}
else {
self->drawing_rel_id++;
if (target) {
new_drawing_rel_id = calloc(1, sizeof(lxw_drawing_rel_id));
if (new_drawing_rel_id) {
new_drawing_rel_id->id = self->drawing_rel_id;
new_drawing_rel_id->target = lxw_strdup(target);
RB_INSERT(lxw_drawing_rel_ids, self->drawing_rel_ids,
new_drawing_rel_id);
}
}
return self->drawing_rel_id;
}
}
/*
* find the index used to address a drawing rel link.
*/
STATIC uint32_t
_find_drawing_rel_index(lxw_worksheet *self, char *target)
{
lxw_drawing_rel_id tmp_drawing_rel_id;
lxw_drawing_rel_id *found_duplicate_target = NULL;
if (!target)
return 0;
tmp_drawing_rel_id.target = target;
found_duplicate_target = RB_FIND(lxw_drawing_rel_ids,
self->drawing_rel_ids,
&tmp_drawing_rel_id);
if (found_duplicate_target)
return found_duplicate_target->id;
else
return 0;
}
/*
@ -2124,27 +2206,38 @@ lxw_worksheet_prepare_image(lxw_worksheet *self,
goto mem_error;
}
STAILQ_INSERT_TAIL(self->drawing_links, relationship, list_pointers);
if (!_find_drawing_rel_index(self, url)) {
STAILQ_INSERT_TAIL(self->drawing_links, relationship,
list_pointers);
}
else {
free(relationship->type);
free(relationship->target);
free(relationship->target_mode);
free(relationship);
}
drawing_object->url_rel_index = _get_drawing_rel_index(self, NULL);
drawing_object->url_rel_index = _get_drawing_rel_index(self, url);
}
drawing_object->rel_index = _get_drawing_rel_index(self, NULL);
if (!_find_drawing_rel_index(self, object_props->md5)) {
relationship = calloc(1, sizeof(lxw_rel_tuple));
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
relationship = calloc(1, sizeof(lxw_rel_tuple));
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
relationship->type = lxw_strdup("/image");
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
relationship->type = lxw_strdup("/image");
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
lxw_snprintf(filename, 32, "../media/image%d.%s", image_ref_id,
object_props->extension);
lxw_snprintf(filename, 32, "../media/image%d.%s", image_ref_id,
object_props->extension);
relationship->target = lxw_strdup(filename);
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
relationship->target = lxw_strdup(filename);
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
STAILQ_INSERT_TAIL(self->drawing_links, relationship, list_pointers);
}
STAILQ_INSERT_TAIL(self->drawing_links, relationship, list_pointers);
drawing_object->rel_index = _get_drawing_rel_index(self, object_props->md5);
return;
@ -2543,9 +2636,11 @@ _get_image_properties(lxw_object_properties *image_props)
{
unsigned char signature[4];
#ifndef USE_NO_MD5
MD5_CTX context;
uint8_t i;
MD5_CTX md5_context;
size_t size_read;
char buffer[LXW_IMAGE_BUFFER_SIZE];
unsigned char md5_checksum[LXW_MD5_SIZE];
#endif
/* Read 4 bytes to look for the file header/signature. */
@ -2576,17 +2671,31 @@ _get_image_properties(lxw_object_properties *image_props)
}
#ifndef USE_NO_MD5
/* Calculate an MD5 checksum for the image so that we can remove duplicate
* images to reduce the xlsx file size.*/
rewind(image_props->stream);
MD5_Init(&context);
size_read = fread(buffer, 1, LXW_IMAGE_BUFFER_SIZE, image_props->stream);
MD5_Init(&md5_context);
size_read = fread(buffer, 1, LXW_IMAGE_BUFFER_SIZE, image_props->stream);
while (size_read) {
MD5_Update(&context, buffer, size_read);
MD5_Update(&md5_context, buffer, size_read);
size_read =
fread(buffer, 1, LXW_IMAGE_BUFFER_SIZE, image_props->stream);
}
MD5_Final(image_props->md5, &context);
MD5_Final(md5_checksum, &md5_context);
/* Create a 32 char hex string buffer for the MD5 checksum. */
image_props->md5 = calloc(1, LXW_MD5_SIZE * 2 + 1);
/* If this calloc fails we just return and don't remove duplicates. */
RETURN_ON_MEM_ERROR(image_props->md5, LXW_NO_ERROR);
/* Convert the 16 byte MD5 buffer to a 32 char hex string. */
for (i = 0; i < LXW_MD5_SIZE; i++) {
lxw_snprintf(&image_props->md5[2 * i], 3, "%02x", md5_checksum[i]);
}
#endif
return LXW_NO_ERROR;

View File

@ -0,0 +1,23 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("test_hyperlink48.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.url = "https://github.com/jmcnamara"};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
worksheet_insert_image_opt(worksheet, CELL("E13"), "images/red.png", &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("test_hyperlink49.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.url = "https://github.com/jmcnamara"};
worksheet_write_url(worksheet, CELL("A1"), "https://github.com/jmcnamara" , NULL);
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,21 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("test_image50.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png");
worksheet_insert_image(worksheet, CELL("E13"), "images/red.png");
return workbook_close(workbook);
}

View File

@ -0,0 +1,47 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
unsigned char image_buffer[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
0x08, 0x02, 0x00, 0x00, 0x00, 0xfc, 0x18, 0xed, 0xa3, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc,
0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00,
0x7a, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00,
0x80, 0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00,
0x3a, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00,
0x00, 0x46, 0x49, 0x44, 0x41, 0x54, 0x48, 0x4b, 0x63, 0xfc, 0xcf, 0x40,
0x63, 0x00, 0xb4, 0x80, 0xa6, 0x88, 0xb6, 0xa6, 0x83, 0x82, 0x87, 0xa6,
0xce, 0x1f, 0xb5, 0x80, 0x98, 0xe0, 0x1d, 0x8d, 0x03, 0x82, 0xa1, 0x34,
0x1a, 0x44, 0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45,
0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0xa3, 0x41,
0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0x03, 0x1f, 0x44, 0x00,
0xaa, 0x35, 0xdd, 0x4e, 0xe6, 0xd5, 0xa1, 0x22, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int image_size = 200;
int main() {
lxw_workbook *workbook = workbook_new("test_image86.xlsx");
lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.description = "red.png"};
worksheet_insert_image_buffer_opt(worksheet1, CELL("E9"), image_buffer, image_size, &options);
worksheet_insert_image_buffer_opt(worksheet2, CELL("E9"), image_buffer, image_size, &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,46 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
unsigned char image_buffer[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
0x08, 0x02, 0x00, 0x00, 0x00, 0xfc, 0x18, 0xed, 0xa3, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc,
0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00,
0x7a, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00,
0x80, 0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00,
0x3a, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00,
0x00, 0x46, 0x49, 0x44, 0x41, 0x54, 0x48, 0x4b, 0x63, 0xfc, 0xcf, 0x40,
0x63, 0x00, 0xb4, 0x80, 0xa6, 0x88, 0xb6, 0xa6, 0x83, 0x82, 0x87, 0xa6,
0xce, 0x1f, 0xb5, 0x80, 0x98, 0xe0, 0x1d, 0x8d, 0x03, 0x82, 0xa1, 0x34,
0x1a, 0x44, 0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45,
0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0xa3, 0x41,
0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0x03, 0x1f, 0x44, 0x00,
0xaa, 0x35, 0xdd, 0x4e, 0xe6, 0xd5, 0xa1, 0x22, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int image_size = 200;
int main() {
lxw_workbook *workbook = workbook_new("test_image87.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.description = "red.png"};
worksheet_insert_image_buffer_opt(worksheet, CELL("E9"), image_buffer, image_size, &options);
worksheet_insert_image_buffer_opt(worksheet, CELL("E13"), image_buffer, image_size, &options);
return workbook_close(workbook);
}

View File

@ -5,6 +5,8 @@
# Copyright 2014-2019, John McNamara, jmcnamara@cpan.org
#
import os
import pytest
import base_test_class
class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
@ -174,3 +176,10 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
def test_hyperlink47(self):
self.run_exe_test('test_hyperlink47')
@pytest.mark.skipif(os.environ.get('USE_NO_MD5'), reason="compiled without MD5 support")
def test_hyperlink48(self):
self.run_exe_test('test_hyperlink48')
def test_hyperlink49(self):
self.run_exe_test('test_hyperlink49')

View File

@ -135,6 +135,10 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
def test_image49(self):
self.run_exe_test('test_image49')
@pytest.mark.skipif(os.environ.get('USE_NO_MD5'), reason="compiled without MD5 support")
def test_image50(self):
self.run_exe_test('test_image50')
# Test in-memory image handling.
def test_image81(self):
self.run_exe_test('test_image81', 'image01.xlsx')
@ -145,6 +149,14 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
def test_image83(self):
self.run_exe_test('test_image83', 'image02.xlsx')
@pytest.mark.skipif(os.environ.get('USE_NO_MD5'), reason="compiled without MD5 support")
def test_image86(self):
self.run_exe_test('test_image86', 'image48.xlsx')
@pytest.mark.skipif(os.environ.get('USE_NO_MD5'), reason="compiled without MD5 support")
def test_image87(self):
self.run_exe_test('test_image87', 'image50.xlsx')
# Test image description fields.
def test_image84(self):
self.run_exe_test('test_image84')

Binary file not shown.

Binary file not shown.

Binary file not shown.