GVKun编程网logo

windows 10上源码编译libjpeg-turbo和使用教程(源码编译软件)

3

如果您对windows10上源码编译libjpeg-turbo和使用教程和源码编译软件感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解windows10上源码编译libjpeg-turbo和使用

如果您对windows 10上源码编译libjpeg-turbo和使用教程源码编译软件感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解windows 10上源码编译libjpeg-turbo和使用教程的各种细节,并对源码编译软件进行深入的分析,此外还有关于AdDuplex:Windows 10 21H1 和 Windows 11 首次进入快速增、Linux/Wine:windows 应用程序启动 windows 控制台命令并在 windows 上等待时在 linux 上不等待:如何修复?、Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计、MSMG ToolKit 11.7 支持 Windows 11 22000 和 Windows 10 21H2的实用技巧。

本文目录一览:

windows 10上源码编译libjpeg-turbo和使用教程(源码编译软件)

windows 10上源码编译libjpeg-turbo和使用教程(源码编译软件)

本文首发于个人博客https://kezunlin.me/post/83828674/,欢迎阅读!

compile and use libjpeg-turbo on windows 10

Series

  • compile and use libjpeg-turbo on windows 10
  • compile and use libjpeg-turbo on ubuntu 16.04

Guide

build requirements

Build Requirements

  • cmake 2.8
  • NASM 2.13
  • Visual Studio 2015
  • libjpeg-turbo 1.5.4
(1) If using NASM, 2.05 or later is required for an x86-64 build.

(2) nasm.exe/yasm.exe should be in your PATH.

download

git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
# or
wget https://codeload.github.com/libjpeg-turbo/libjpeg-turbo/zip/master

install nasm

wget http://www.nasm.us/pub/nasm/releasebuilds/2.13.03rc1/win64/nasm-2.13.03rc1-installer-x64.exe

add C:\Program Files\NASM to env path.

## compile libjpeg

cmake-gui

CMAKE_BUILD_TYPE = Release
ENABLE_SHARED = ON
CMAKE_INSTALL_PREFIX = d:/libjpeg-turbo64
NASM = C:/Program Files/NASM/nasm.exe

configure and generate sln, compile with visual studio 2015 and install.

## usage with cmake

### libjpegturbo-config.cmake

set(LIBJPEGTURBO_FOUND TRUE) # auto 
set(LIBJPEGTURBO_ROOT_DIR "d:/libjpeg-turbo64")

find_path(LIBJPEGTURBO_INCLUDE_DIR NAMES jpeglib.h turbojpeg.h PATHS "${LIBJPEGTURBO_ROOT_DIR}/include") 
mark_as_advanced(LIBJPEGTURBO_INCLUDE_DIR) # show entry in cmake-gui

find_library(LIBJPEGTURBO_JPEG_LIBRARY NAMES jpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib") 
mark_as_advanced(LIBJPEGTURBO_JPEG_LIBRARY) # show entry in cmake-gui

find_library(LIBJPEGTURBO_TURBOJPEG_LIBRARY NAMES turbojpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib") 
mark_as_advanced(LIBJPEGTURBO_TURBOJPEG_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(LIBJPEGTURBO_INCLUDE_DIRS ${LIBJPEGTURBO_INCLUDE_DIR} )
set(LIBJPEGTURBO_LIBRARIES ${LIBJPEGTURBO_JPEG_LIBRARY} ${LIBJPEGTURBO_TURBOJPEG_LIBRARY} )

message( "libjpegturbo-config.cmake " ${LIBJPEGTURBO_ROOT_DIR})

### CMakeLists.txt

find_package(LIBJPEGTURBO REQUIRED)
include_directories(${LIBJPEGTURBO_INCLUDE_DIRS})  

add_executable (example_jpeg
   ${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_jpeg.cpp
)

target_link_libraries (example_jpeg 
   ${LIBJPEGTURBO_LIBRARIES}
)

add_executable (example_turbojpeg
   ${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_turbojpeg.cpp
)

target_link_libraries (example_turbojpeg 
   ${LIBJPEGTURBO_LIBRARIES}
)

Example Code

jpeglib vs turbojpeg

jpeglib

  • include: #include "jpeglib.h"
  • lib: jpeg.lib
  • dll: jpeg62.dll

turbojpeg

  • include: #include "turbojpeg.h"
  • lib: turbojpeg.lib
  • dll: turbojpeg.dll

turbojpeg is (3-5x) faster than jpeglib.

jpeglib

#include <iostream>
#include <fstream>
#include <ctime>

#include "jpeglib.h"

typedef unsigned char BYTE;

bool CompressJPEG(
    /*IN*/BYTE *src, int width, int height, int depth,
    /*OUT*/BYTE **dst, unsigned long *dstLen
)
{
    // NOTICE: dst space must be created outside before passing in.
    struct jpeg_compress_struct jcs;
    struct jpeg_error_mgr jem;
    jcs.err = jpeg_std_error(&jem);

    jpeg_create_compress(&jcs);
    jpeg_mem_dest(&jcs, dst, dstLen);
    jcs.image_width = width;
    jcs.image_height = height;
    jcs.input_components = depth;
    jcs.in_color_space = JCS_RGB;

    jpeg_set_defaults(&jcs);
    jpeg_set_quality(&jcs, 80, true);

    jcs.jpeg_color_space = JCS_YCbCr;
    jcs.comp_info[0].h_samp_factor = 2;
    jcs.comp_info[0].v_samp_factor = 2;

    jpeg_start_compress(&jcs, TRUE);
    JSAMPROW row_pointer[1];
    int row_stride = jcs.image_width*jcs.num_components;
    while (jcs.next_scanline<jcs.image_height)
    {
        row_pointer[0] = &src[jcs.next_scanline*row_stride];
        jpeg_write_scanlines(&jcs, row_pointer, 1);
    }
    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);

    return true;
}

bool DeompressJPEG(
    /*IN*/BYTE *src, unsigned long srcLen,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *depth
)
{
    // NOTICE: dst space will be created inside.
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err=jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    jpeg_mem_src(&cinfo,src,srcLen);
    jpeg_read_header(&cinfo,TRUE);

    jpeg_start_decompress(&cinfo);
    (*width) = cinfo.output_width;
    (*height) = cinfo.output_height;
    (*depth) = cinfo.num_components;
    (*dstLen) = (*width)*(*height)*(*depth);
    BYTE *tmp_dst = new BYTE[*dstLen];

    JSAMPROW row_pointer[1];
    int row_stride = cinfo.image_width*cinfo.num_components;
    while (cinfo.output_scanline<cinfo.output_height)
    {
        row_pointer[0] = &tmp_dst[cinfo.output_scanline*row_stride];
        jpeg_read_scanlines(&cinfo,row_pointer,1);
    }
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    *dst = tmp_dst;

    return true;
}

void compress_jpeg_to_file(
    /*IN*/BYTE *src,int width, int height, int components, int color_space,int quality,
    /*OUT*/char *dst_filename
)
{
    /* This struct contains the JPEG compression parameters and pointers to
    * working space (which is allocated as needed by the JPEG library).
    * It is possible to have several such structures, representing multiple
    * compression/decompression processes, in existence at once.  We refer
    * to any one struct (and its associated working data) as a "JPEG object".
    */
    struct jpeg_compress_struct cinfo;
    /* This struct represents a JPEG error handler.  It is declared separately
    * because applications often want to supply a specialized error handler
    * (see the second half of this file for an example).  But here we just
    * take the easy way out and use the standard error handler, which will
    * print a message on stderr and call exit() if compression fails.
    * Note that this struct must live as long as the main JPEG parameter
    * struct, to avoid dangling-pointer problems.
    */
    struct jpeg_error_mgr jerr;
    /* More stuff */
    FILE *outfile;                /* target file */
    JSAMPROW row_pointer[1];      /* pointer to JSAMPLE row[s] */
    int row_stride;               /* physical row width in image buffer */

    /* Step 1: allocate and initialize JPEG compression object */

    /* We have to set up the error handler first, in case the initialization
    * step fails.  (Unlikely, but it could happen if you are out of memory.)
    * This routine fills in the contents of struct jerr, and returns jerr''s
    * address which we place into the link field in cinfo.
    */
    cinfo.err = jpeg_std_error(&jerr);
    /* Now we can initialize the JPEG compression object. */
    jpeg_create_compress(&cinfo);

    /* Step 2: specify data destination (eg, a file) */
    /* Note: steps 2 and 3 can be done in either order. */

    /* Here we use the library-supplied code to send compressed data to a
    * stdio stream.  You can also write your own code to do something else.
    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
    * requires it in order to write binary files.
    */
    if ((outfile = fopen(dst_filename, "wb")) == NULL) {
        fprintf(stderr, "can''t open %s\n", dst_filename);
        exit(1);
    }
    jpeg_stdio_dest(&cinfo, outfile);

    /* Step 3: set parameters for compression */

    /* First we supply a description of the input image.
    * Four fields of the cinfo struct must be filled in:
    */
    cinfo.image_width = width;      /* image width and height, in pixels */
    cinfo.image_height = height;
    cinfo.input_components = components;           /* # of color components per pixel */
    cinfo.in_color_space = (J_COLOR_SPACE)color_space;       /* colorspace of input image */
    /* Now use the library''s routine to set default compression parameters.
    * (You must set at least cinfo.in_color_space before calling this,
    * since the defaults depend on the source color space.)
    */
    jpeg_set_defaults(&cinfo);
    /* Now you can set any non-default parameters you wish to.
    * Here we just illustrate the use of quality (quantization table) scaling:
    */
    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

    /* Step 4: Start compressor */

    /* TRUE ensures that we will write a complete interchange-JPEG file.
    * Pass TRUE unless you are very sure of what you''re doing.
    */
    jpeg_start_compress(&cinfo, TRUE);

    /* Step 5: while (scan lines remain to be written) */
    /*           jpeg_write_scanlines(...); */

    /* Here we use the library''s state variable cinfo.next_scanline as the
    * loop counter, so that we don''t have to keep track ourselves.
    * To keep things simple, we pass one scanline per call; you can pass
    * more if you wish, though.
    */
    row_stride = cinfo.image_width * cinfo.input_components; /* JSAMPLEs per row in image_buffer */

    while (cinfo.next_scanline < cinfo.image_height) {
        /* jpeg_write_scanlines expects an array of pointers to scanlines.
        * Here the array is only one element long, but you could pass
        * more than one scanline at a time if that''s more convenient.
        */
        row_pointer[0] = &src[cinfo.next_scanline * row_stride];
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    /* Step 6: Finish compression */

    jpeg_finish_compress(&cinfo);
    /* After finish_compress, we can close the output file. */
    fclose(outfile);

    /* Step 7: release JPEG compression object */

    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_compress(&cinfo);

    /* And we''re done! */
}

void compress_jpeg_to_mem(
    /*IN*/BYTE *src,int width, int height, int components, int color_space,int quality,
    /*OUT*/BYTE **dst, unsigned long *dstLen
)
{
    /* This struct contains the JPEG compression parameters and pointers to
    * working space (which is allocated as needed by the JPEG library).
    * It is possible to have several such structures, representing multiple
    * compression/decompression processes, in existence at once.  We refer
    * to any one struct (and its associated working data) as a "JPEG object".
    */
    struct jpeg_compress_struct cinfo;
    /* This struct represents a JPEG error handler.  It is declared separately
    * because applications often want to supply a specialized error handler
    * (see the second half of this file for an example).  But here we just
    * take the easy way out and use the standard error handler, which will
    * print a message on stderr and call exit() if compression fails.
    * Note that this struct must live as long as the main JPEG parameter
    * struct, to avoid dangling-pointer problems.
    */
    struct jpeg_error_mgr jerr;
    /* More stuff */
    //FILE *outfile;                /* target file */
    JSAMPROW row_pointer[1];      /* pointer to JSAMPLE row[s] */
    int row_stride;               /* physical row width in image buffer */

    /* Step 1: allocate and initialize JPEG compression object */

    /* We have to set up the error handler first, in case the initialization
    * step fails.  (Unlikely, but it could happen if you are out of memory.)
    * This routine fills in the contents of struct jerr, and returns jerr''s
    * address which we place into the link field in cinfo.
    */
    cinfo.err = jpeg_std_error(&jerr);
    /* Now we can initialize the JPEG compression object. */
    jpeg_create_compress(&cinfo);

    /* Step 2: specify data destination (eg, a file) */
    /* Note: steps 2 and 3 can be done in either order. */
    //jpeg_stdio_dest(&cinfo, outfile);
    jpeg_mem_dest(&cinfo, dst, dstLen);

    /* Step 3: set parameters for compression */

    /* First we supply a description of the input image.
    * Four fields of the cinfo struct must be filled in:
    */
    cinfo.image_width = width;      /* image width and height, in pixels */
    cinfo.image_height = height;
    cinfo.input_components = components;           /* # of color components per pixel */
    cinfo.in_color_space = (J_COLOR_SPACE)color_space;       /* colorspace of input image */
    /* Now use the library''s routine to set default compression parameters.
    * (You must set at least cinfo.in_color_space before calling this,
    * since the defaults depend on the source color space.)
    */
    jpeg_set_defaults(&cinfo);
    /* Now you can set any non-default parameters you wish to.
    * Here we just illustrate the use of quality (quantization table) scaling:
    */
    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

    /* Step 4: Start compressor */

    /* TRUE ensures that we will write a complete interchange-JPEG file.
    * Pass TRUE unless you are very sure of what you''re doing.
    */
    jpeg_start_compress(&cinfo, TRUE);

    /* Step 5: while (scan lines remain to be written) */
    /*           jpeg_write_scanlines(...); */

    /* Here we use the library''s state variable cinfo.next_scanline as the
    * loop counter, so that we don''t have to keep track ourselves.
    * To keep things simple, we pass one scanline per call; you can pass
    * more if you wish, though.
    */
    row_stride = cinfo.image_width * cinfo.input_components; /* JSAMPLEs per row in image_buffer */

    while (cinfo.next_scanline < cinfo.image_height) {
        /* jpeg_write_scanlines expects an array of pointers to scanlines.
        * Here the array is only one element long, but you could pass
        * more than one scanline at a time if that''s more convenient.
        */
        row_pointer[0] = &src[cinfo.next_scanline * row_stride];
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    /* Step 6: Finish compression */

    jpeg_finish_compress(&cinfo);
    /* After finish_compress, we can close the output file. */
    //fclose(outfile);

    /* Step 7: release JPEG compression object */

    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_compress(&cinfo);

    /* And we''re done! */
}

int    decompress_jpeg_from_file(
    /*IN*/char *src_filename,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *components,int *color_space)
{
    /* This struct contains the JPEG decompression parameters and pointers to
    * working space (which is allocated as needed by the JPEG library).
    */
    struct jpeg_decompress_struct cinfo;
    /* We use our private extension JPEG error handler.
    * Note that this struct must live as long as the main JPEG parameter
    * struct, to avoid dangling-pointer problems.
    */
    struct jpeg_error_mgr jerr;
    /* More stuff */
    FILE *infile;                 /* source file */
    int row_stride;               /* physical row width in output buffer */

    /* In this example we want to open the input file before doing anything else,
    * so that the setjmp() error recovery below can assume the file is open.
    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
    * requires it in order to read binary files.
    */

    if ((infile = fopen(src_filename, "rb")) == NULL) {
        fprintf(stderr, "can''t open %s\n", src_filename);
        return 0;
    }

    /* Step 1: allocate and initialize JPEG decompression object */

    /* We set up the normal JPEG error routines, then override error_exit. */
    cinfo.err = jpeg_std_error(&jerr);
    /* Now we can initialize the JPEG decompression object. */
    jpeg_create_decompress(&cinfo);

    /* Step 2: specify data source (eg, a file) */

    jpeg_stdio_src(&cinfo, infile);

    /* Step 3: read file parameters with jpeg_read_header() */

    (void)jpeg_read_header(&cinfo, TRUE);
    /* We can ignore the return value from jpeg_read_header since
    *   (a) suspension is not possible with the stdio data source, and
    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
    * See libjpeg.txt for more info.
    */

    /* Step 4: set parameters for decompression */

    /* In this example, we don''t need to change any of the defaults set by
    * jpeg_read_header(), so we do nothing here.
    */

    /* Step 5: Start decompressor */

    (void)jpeg_start_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
    * with the stdio data source.
    */

    /* We may need to do some setup of our own at this point before reading
    * the data.  After jpeg_start_decompress() we have the correct scaled
    * output image dimensions available, as well as the output colormap
    * if we asked for color quantization.
    * In this example, we need to make an output work buffer of the right size.
    */
    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    
    /* Set output fields */
    (*width) = cinfo.output_width;
    (*height) = cinfo.output_height;
    (*components) = cinfo.num_components;
    (*color_space) = cinfo.jpeg_color_space;
    (*dstLen) = (*width)*(*height)*(*components);
    BYTE *tmp_dst = new BYTE[*dstLen]; /* Allocate out buffer */

    JSAMPROW row_pointer[1];
    row_stride = cinfo.output_width*cinfo.num_components;
    /* Step 6: while (scan lines remain to be read) */
    /*           jpeg_read_scanlines(...); */

    /* Here we use the library''s state variable cinfo.output_scanline as the
    * loop counter, so that we don''t have to keep track ourselves.
    */
    while (cinfo.output_scanline < cinfo.output_height) {
        /* jpeg_read_scanlines expects an array of pointers to scanlines.
        * Here the array is only one element long, but you could ask for
        * more than one scanline at a time if that''s more convenient.
        */
        row_pointer[0] = &tmp_dst[cinfo.output_scanline*row_stride];
        (void)jpeg_read_scanlines(&cinfo, row_pointer, 1);
    }
    (*dst) = tmp_dst; // assign to outside dst 

    /* Step 7: Finish decompression */

    (void)jpeg_finish_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
    * with the stdio data source.
    */

    /* Step 8: Release JPEG decompression object */

    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_decompress(&cinfo);

    /* After finish_decompress, we can close the input file.
    * Here we postpone it until after no more JPEG errors are possible,
    * so as to simplify the setjmp error logic above.  (Actually, I don''t
    * think that jpeg_destroy can do an error exit, but why assume anything...)
    */
    fclose(infile);

    /* At this point you may want to check to see whether any corrupt-data
    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
    */

    /* And we''re done! */
    return 1;
}

int    decompress_jpeg_from_mem(
    /*IN*/BYTE *src, unsigned long srcLen,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *components, int *color_space)
{
    /* This struct contains the JPEG decompression parameters and pointers to
    * working space (which is allocated as needed by the JPEG library).
    */
    struct jpeg_decompress_struct cinfo;
    /* We use our private extension JPEG error handler.
    * Note that this struct must live as long as the main JPEG parameter
    * struct, to avoid dangling-pointer problems.
    */
    struct jpeg_error_mgr jerr;
    /* More stuff */
    //FILE *infile;                 /* source file */
    int row_stride;               /* physical row width in output buffer */

    /* In this example we want to open the input file before doing anything else,
    * so that the setjmp() error recovery below can assume the file is open.
    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
    * requires it in order to read binary files.
    */

    /*
    if ((infile = fopen(src_filename, "rb")) == NULL) {
        fprintf(stderr, "can''t open %s\n", src_filename);
        return 0;
    }
    */

    /* Step 1: allocate and initialize JPEG decompression object */

    /* We set up the normal JPEG error routines, then override error_exit. */
    cinfo.err = jpeg_std_error(&jerr);
    /* Now we can initialize the JPEG decompression object. */
    jpeg_create_decompress(&cinfo);

    /* Step 2: specify data source (eg, a file) */

    //jpeg_stdio_src(&cinfo, infile);
    jpeg_mem_src(&cinfo, src, srcLen);

    /* Step 3: read file parameters with jpeg_read_header() */

    (void)jpeg_read_header(&cinfo, TRUE);
    /* We can ignore the return value from jpeg_read_header since
    *   (a) suspension is not possible with the stdio data source, and
    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
    * See libjpeg.txt for more info.
    */

    /* Step 4: set parameters for decompression */

    /* In this example, we don''t need to change any of the defaults set by
    * jpeg_read_header(), so we do nothing here.
    */

    /* Step 5: Start decompressor */

    (void)jpeg_start_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
    * with the stdio data source.
    */

    /* We may need to do some setup of our own at this point before reading
    * the data.  After jpeg_start_decompress() we have the correct scaled
    * output image dimensions available, as well as the output colormap
    * if we asked for color quantization.
    * In this example, we need to make an output work buffer of the right size.
    */
    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */

    /* Set output fields */
    (*width) = cinfo.output_width;
    (*height) = cinfo.output_height;
    (*components) = cinfo.num_components;
    (*color_space) = cinfo.jpeg_color_space;
    (*dstLen) = (*width)*(*height)*(*components);
    BYTE *tmp_dst = new BYTE[*dstLen]; /* Allocate out buffer */

    JSAMPROW row_pointer[1];
    row_stride = cinfo.output_width*cinfo.num_components;
    /* Step 6: while (scan lines remain to be read) */
    /*           jpeg_read_scanlines(...); */

    /* Here we use the library''s state variable cinfo.output_scanline as the
    * loop counter, so that we don''t have to keep track ourselves.
    */
    while (cinfo.output_scanline < cinfo.output_height) {
        /* jpeg_read_scanlines expects an array of pointers to scanlines.
        * Here the array is only one element long, but you could ask for
        * more than one scanline at a time if that''s more convenient.
        */
        row_pointer[0] = &tmp_dst[cinfo.output_scanline*row_stride];
        (void)jpeg_read_scanlines(&cinfo, row_pointer, 1);
    }
    (*dst) = tmp_dst; // assign to outside dst 

    /* Step 7: Finish decompression */

    (void)jpeg_finish_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
    * with the stdio data source.
    */

    /* Step 8: Release JPEG decompression object */

    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_decompress(&cinfo);

    /* After finish_decompress, we can close the input file.
    * Here we postpone it until after no more JPEG errors are possible,
    * so as to simplify the setjmp error logic above.  (Actually, I don''t
    * think that jpeg_destroy can do an error exit, but why assume anything...)
    */
    //fclose(infile);

    /* At this point you may want to check to see whether any corrupt-data
    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
    */

    /* And we''re done! */
    return 1;
}

void test_compress_to_file()
{
    int width = 2000;
    int height = 1000;
    int channel = 1;

    int nImgSize = width * height * channel;
    unsigned char * pRawImage = new unsigned char[nImgSize]; // new buffer
    memset(pRawImage, 0, nImgSize);
    for (int i = 100; i < 300; i++) // row [height]
    {
        for (int j = 0; j < width; j++) // column [width]
        {
            *(pRawImage + width * i + j) = (char)255;
        }
    }

    // do work.
    compress_jpeg_to_file(
        pRawImage,width,height,channel,J_COLOR_SPACE::JCS_GRAYSCALE,90, 
        "../image/compress/to_file.jpg"
    );

    delete[] pRawImage;
}

void test_compress_to_mem()
{
    int width = 2000;
    int height = 1000;
    int channel = 1;

    int nImgSize = width * height * channel;
    unsigned char * pRawImage = new unsigned char[nImgSize]; // new buffer
    memset(pRawImage, 0, nImgSize);
    for (int i = 100; i < 300; i++) // row [height]
    {
        for (int j = 0; j < width; j++) // column [width]
        {
            *(pRawImage + width * i + j) = (char)255;
        }
    }

    // (1) new dst space outside **compress** function
    // pOutBuffer''s nImgSize must > lOutSize to contain valid dst buffer.
    unsigned char *pOutBuffer = new unsigned char[nImgSize]; // new dst buffer
    unsigned long lOutSize = 0;

    // (2) compress to mem
    compress_jpeg_to_mem(
        pRawImage, width, height, channel, J_COLOR_SPACE::JCS_GRAYSCALE, 90,
        &pOutBuffer, &lOutSize
    );

    std::cout << "orginal size = " << nImgSize << std::endl;
    std::cout << "compress size = "<<lOutSize << std::endl; // 30403

    // (3) write mem buffer to file 
    const char* dst_filename = "../image/compress/mem_to_file.jpg";
    FILE *outfile;
    if ((outfile = fopen(dst_filename, "wb")) == NULL) {
        fprintf(stderr, "can''t open %s\n", dst_filename);
        exit(1);
    }
    fwrite(pOutBuffer,lOutSize,1,outfile);
    fclose(outfile);

    delete[] pOutBuffer;

    delete[] pRawImage;
}

void test_decompress_from_file()
{
    char* src_filename = "../image/compress/to_file.jpg";
    BYTE *dst = NULL; // raw image buffer allocated inside **decompress** function
    unsigned long dstLen;
    int width, height, channel,color_space;

    // allocate dst inside function
    decompress_jpeg_from_file(
        src_filename,
        &dst,&dstLen,&width,&height,&channel,&color_space
    );

    std::cout << dstLen << std::endl;
    std::cout << width << std::endl;
    std::cout << height << std::endl;
    std::cout << channel << std::endl;
    std::cout << color_space << std::endl;

    // use raw image buffer
    // do work.
    compress_jpeg_to_file(
        dst, width, height, channel, J_COLOR_SPACE::JCS_GRAYSCALE, 90,
        "../image/compress/decompress_from_file_and_then_to_file.jpg"
    );

    // free allocated memory
    if (dst != NULL)
    {
        delete[] dst;
    }
}

void test_decompress_from_mem()
{
    // (0) create memory src buffer
    char* src_filename = "../image/compress/to_file.jpg";
    std::ifstream ifs(src_filename, std::ios_base::binary | std::ios_base::in);
    ifs.seekg(0, std::ios::end);
    uint64_t size = ifs.tellg();
    ifs.seekg(0, std::ios::beg);

    //std::vector<char> buffer(size);
    //ifs.read(&buffer.front(), size);
    BYTE *src = new BYTE[size];
    ifs.read((char*)src, size);

    // (1) decompress from mem
    BYTE *dst = NULL; // raw image buffer allocated inside **decompress** function
    unsigned long dstLen;
    int width, height, channel, color_space;

    // allocate dst inside function
    decompress_jpeg_from_mem(
        src,size,
        &dst, &dstLen, &width, &height, &channel, &color_space
    );

    std::cout << dstLen << std::endl;
    std::cout << width << std::endl;
    std::cout << height << std::endl;
    std::cout << channel << std::endl;
    std::cout << color_space << std::endl;

    // (2) use raw image buffer
    // do work.
    compress_jpeg_to_file(
        dst, width, height, channel, J_COLOR_SPACE::JCS_GRAYSCALE, 90,
        "../image/compress/decompress_from_mem_and_then_to_file.jpg"
    );
    // free dst allocated memory
    if (dst != NULL)
    {
        delete[] dst;
    }

    // free src memory buffer
    delete[] src;
}


int IMAGE_COUNT = 10000;
void test_compress_time()
{
    int width = 2000;
    int height = 1000;
    int channel = 1;

    unsigned long srcLen = width * height * channel;
    unsigned char * src = new unsigned char[srcLen]; // new buffer
    memset(src, 0, srcLen);
    for (int i = 100; i < 300; i++) // row [height]
    {
        for (int j = 0; j < width; j++) // column [width]
        {
            *(src + width * i + j) = (char)255;
        }
    }

    int quality = 90;
    time_t start = time(NULL);

    for (int i = 0; i < IMAGE_COUNT; i++)
    {
        // (1) new dst space outside **compress** function
        // pOutBuffer''s nImgSize must > lOutSize to contain valid dst buffer.
        unsigned char *pOutBuffer = new unsigned char[srcLen]; // new dst buffer
        unsigned long lOutSize = 0;

        // (2) compress to mem
        compress_jpeg_to_mem(
            src, width, height, channel, J_COLOR_SPACE::JCS_GRAYSCALE, 90,
            &pOutBuffer, &lOutSize
        );

        // (3) free memory
        delete[] pOutBuffer;
    }

    time_t end = time(NULL);
    std::cout << "======================================" << std::endl;
    double ms = (double)(end - start) * 1000;
    std::cout << " use times = " << ms << "ms; avg = " << ms / IMAGE_COUNT << " ms; " << " #" << IMAGE_COUNT << std::endl;
    // avg = 4.9 ms  #10000 for jpeg
    // avg = 4.5 ms  #10000 for turbojpeg
    std::cout << "======================================" << std::endl;


    delete[] src;
}

void test_decompress_time()
{

}

int main(int argc, char* argv[])
{
    // 30403, 30153
    //test_compress_to_file();
    //test_compress_to_mem();
    //test_decompress_from_file();
    //test_decompress_from_mem();

    test_compress_time();
    return 0;
}

turbojpeg

#include <iostream>
#include <fstream>
#include <vector>
#include <ctime>

#include "turbojpeg.h"

typedef unsigned char BYTE;

void save_buffer_to_file(const char *filename,BYTE* buffer,unsigned long size)
{
    FILE *outfile;
    if ((outfile = fopen(filename, "wb")) != NULL) {
        fwrite(buffer, size, 1, outfile);
        fclose(outfile);
    }
    else
    {
        fprintf(stderr, "can''t open %s\n", filename);
        exit(1);
    }
}

/*
* Compress image buffer to a JPEG image in memory.
*
* @@input
*
* @param : [src] pointer to an image buffer that will be compressed.
* @param : 
*
* @@output
* @param : [dst] pointer to an image buffer that will receive the compressed image.
           This variable should be passed in with NULL, and will be allocated by 
           TurboJPEG(either by tjAlloc(),or by the Compress/Decompress) method 
           So we need to use tjFree() to free memory allocated after we are done 
           working on dst.
* @param : [dstLen] size of dst image buffer in bytes. This should be passed in with
           value 0.
*
* @@return
* @param void
*
* @@demo
*  
        BYTE *dst = NULL;
        unsigned long dstLen = 0;
        tj_compress_jpeg_to_mem(
            ....,
            &dst,&dstLen
        )
*/
void tj_compress_jpeg_to_mem(
    /*IN*/BYTE *src, int width, int height, int pixelFormat, int subsamp, int quality, int flags,
    /*OUT*/BYTE **dst, unsigned long *dstLen
)
{
    // NOTICE : we must use tjAlloc() and tjFree() to allocate dst buffer.
    // for compress, we let **tjCompress2** allocate dst buffer.
    // for decompress, we allocate dst buffer by ourself.

    tjhandle handle = tjInitCompress();
    //tjCompress2(handle, src, width, 0/*pitch*/, height, TJPF::TJPF_GRAY,
    //    &pOutBuffer, &lOutSize, TJSAMP::TJSAMP_GRAY, quality,
    //    TJFLAG_FASTDCT); //TJFLAG_FASTDCT

    tjCompress2(
        handle, src, width, 0/*pitch*/, height, pixelFormat,
        dst, dstLen, subsamp, quality, flags
    );

    tjDestroy(handle);
}

void tj_compress_gray_jpeg_to_mem(
    /*IN*/BYTE *src, int width, int height, int quality,
    /*OUT*/BYTE **dst, unsigned long *dstLen
)
{
    int pixelFormat = TJPF::TJPF_GRAY;
    int subsamp = TJSAMP::TJSAMP_GRAY;
    int flags = TJFLAG_FASTDCT;

    tj_compress_jpeg_to_mem(
        src, width, height, pixelFormat, subsamp, quality, flags,
        dst, dstLen
    );
}

void tj_compress_gray_jpeg_to_file(
    /*IN*/BYTE *src, int width, int height, int quality,
    /*OUT*/const char* dst_filename
)
{
    int pixelFormat = TJPF::TJPF_GRAY;
    int subsamp = TJSAMP::TJSAMP_GRAY;
    int flags = TJFLAG_FASTDCT;

    // (1) init dst memory buffer
    BYTE *dst = NULL; // memory allocated by TurboJPEG tjAlloc()
    unsigned long dstLen = 0;

    // (2) compress
    tj_compress_jpeg_to_mem(
        src, width, height, pixelFormat, subsamp, quality, flags,
        &dst, &dstLen
    );

    // (3) write buffer to file
    save_buffer_to_file(dst_filename, dst, dstLen);

    // (4) free memory allocated by TurboJPEG
    tjFree(dst);
}


/*
* Compress image buffer to a JPEG image in memory.
*
* @@input
*
* @param : [src] pointer to an image buffer that will be compressed.
* @param :
*
* @@output
* @param : [dst] pointer to an image buffer that will receive the decompressed image.
           This variable should be passed in with NULL, and will be allocated in
           method by new[]. So we need to use delete[] to free memory allocated 
           after we are done working on dst.
* @param : [dstLen] size of dst image buffer in bytes. This should be passed in with
            value 0.
*
* @@return
* @param void
*
* @@demo
*
        BYTE *dst = NULL;
        unsigned long dstLen = 0;
        tj_decompress_jpeg_from_mem(
        ....,
        &dst,&dstLen
        )
*/
void tj_decompress_jpeg_from_mem(
    /*IN*/BYTE *src, unsigned long srcLen,int tjPixelFormat,int flags,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *components, int *jpegSubsamp, int *jpegColorspace)
{
    tjhandle handle = tjInitDecompress();
    tjDecompressHeader3(handle, src, srcLen, width, height, jpegSubsamp, jpegColorspace);

    (*components) = tjPixelSize[(TJPF)tjPixelFormat]; // 1 for GRAY,3 for RGB
    (*dstLen) = (*width) * (*height) * (*components);

    BYTE *tmp_dst = new BYTE[*dstLen]; /* Allocate out buffer */

    tjDecompress2(
        handle, src, srcLen, 
        tmp_dst, *width, 0/*pitch*/, *height, tjPixelFormat, flags
    );
    tjDestroy(handle);

    (*dst) = tmp_dst; // pass dst out
}

void tj_decompress_gray_jpeg_from_mem(
    /*IN*/BYTE *src, unsigned long srcLen,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *components
)
{
    int pixelFormat = TJPF::TJPF_GRAY;
    int flags = TJFLAG_ACCURATEDCT;
    int subsamp,colorspace; // no use for now  (3 TJSAMP::TJSAMP_GRAY, 2 TJCS::TJCS_GRAY)

    tj_decompress_jpeg_from_mem(
        src, srcLen, pixelFormat, flags,
        dst, dstLen, width, height, components, &subsamp, &colorspace
    );
}

void tj_decompress_gray_jpeg_from_file(
    /*IN*/const char* src_filename,
    /*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *components
)
{
    // (0) read src memory buffer from file
    std::ifstream ifs(src_filename, std::ios_base::binary | std::ios_base::in);
    ifs.seekg(0, std::ios::end);
    uint64_t srcLen = ifs.tellg();
    ifs.seekg(0, std::ios::beg);

    BYTE *src = new BYTE[srcLen];
    ifs.read((char*)src, srcLen);

    // (2) decompress  
    int pixelFormat = TJPF::TJPF_GRAY;
    int flags = TJFLAG_ACCURATEDCT;
    int subsamp, colorspace; // no use for now  (3 TJSAMP::TJSAMP_GRAY, 2 TJCS::TJCS_GRAY)

    tj_decompress_jpeg_from_mem(
        src, srcLen, pixelFormat, flags,
        dst, dstLen, width, height, components, &subsamp, &colorspace
    );

    // (3) free src memory buffer
    delete[] src;

    // (4) pass out dst buffer 
}


void test_compress()
{
    int width = 2000;
    int height = 1000;
    int channel = 1;

    unsigned long srcLen = width * height * channel;
    unsigned char * src = new unsigned char[srcLen]; // new buffer
    memset(src, 0, srcLen);
    for (int i = 100; i < 300; i++) // row [height]
    {
        for (int j = 0; j < width; j++) // column [width]
        {
            *(src + width * i + j) = (char)255;
        }
    }

    //========================================================================
    // compress to file
    int quality = 90;
    const char* filename = "../image/compress/tj_mem_to_file.jpg";
    tj_compress_gray_jpeg_to_file(src, width, height, quality, filename);
    //========================================================================

    delete[] src;
}

void test_decompress()
{
    // (0) create memory src buffer
    char* src_filename = "../image/compress/to_file.jpg";
    
    // (2) decompress
    BYTE *dst = NULL; // allocated inside **decompress** function by new[].
    unsigned long dstLen = 0;
    int width, height, components;

    tj_decompress_gray_jpeg_from_file(
        src_filename,
        &dst, &dstLen, &width, &height, &components
    );

    std::cout << dstLen << std::endl;
    std::cout << width << std::endl;
    std::cout << height << std::endl;
    std::cout << components << std::endl;
    
    // (3) use dst buffer
    //========================================================================
    // compress to file
    int quality = 90;
    const char* dst_filename = "../image/compress/tj_decompress_to_mem_to_file.jpg";
    tj_compress_gray_jpeg_to_file(dst, width, height, quality, dst_filename);
    //========================================================================

    // (4) free dst buffer
    delete[] dst;
}


int IMAGE_COUNT = 10000;
void test_compress_time()
{
    int width = 2000;
    int height = 1000;
    int channel = 1;

    unsigned long srcLen = width * height * channel;
    unsigned char * src = new unsigned char[srcLen]; // new buffer
    memset(src, 0, srcLen);
    for (int i = 100; i < 300; i++) // row [height]
    {
        for (int j = 0; j < width; j++) // column [width]
        {
            *(src + width * i + j) = (char)255;
        }
    }

    int quality = 90;
    time_t start = time(NULL);

    for (int i = 0; i < IMAGE_COUNT; i++)
    {
        //========================================================================
        // (1) init dst memory buffer
        BYTE *dst = NULL; // memory allocated by TurboJPEG tjAlloc()
        unsigned long dstLen = 0;

        // (2) compress
        tj_compress_gray_jpeg_to_mem(
            src, width, height, quality,
            &dst, &dstLen
        );

        // (3) free memory allocated by TurboJPEG
        tjFree(dst);
        //========================================================================
    }

    time_t end = time(NULL);
    std::cout << "======================================" << std::endl;
    double ms = (double)(end - start) * 1000;
    std::cout << " use times = " << ms << "ms; avg = " << ms / IMAGE_COUNT << " ms; " << " #" << IMAGE_COUNT << std::endl;
    // avg = 4.9 ms  #10000 for jpeg
    // avg = 4.5 ms  #10000 for turbojpeg
    std::cout << "======================================" << std::endl;

    delete[] src;
}

void test_decompress_time()
{

}

int main(int argc, char* argv[])
{
    //test_compress();
    //test_decompress();
    test_compress_time();
    return 0;
}

Reference

  • example.c
  • building
  • turbo offical doc
  • compress and decompress jpeg
  • opencv imdecode to libjpeg-turbo (good)
  • tjcompress and tjdecompress

History

  • 20180201: created.
  • 20180202: add example code.

Copyright

  • Post author: kezunlin
  • Post link: https://kezunlin.me/post/83828674/
  • Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

AdDuplex:Windows 10 21H1 和 Windows 11 首次进入快速增

AdDuplex:Windows 10 21H1 和 Windows 11 首次进入快速增

AdDuplex 关于 Windows 10 统计数据的最后一份报告是几个月前的。从那以后发生了很多事情。因为Windows 10 2004的比例明显缩水,Windows 10 21H1的比例有所增加。

AdDuplex:Windows 10 21H1 和 Windows 11 首次进入快速增长 - 2021 年 7 月

事实上,现在有 26.6% 的用户在使用 Windows 10 21H1。Windows 10 20H2 的份额从 40.1% 下降到 36.3%,而 2004 年的份额从 40.6% 下降到“仅”24.6%。

有趣的是内部版本用户数量的增加。这里的比例通常最多在 0.4% 和 0.7% 之间波动。但现在仅 Windows 11 就已经拥有 0.9% 的份额,Windows 10 Insider 已经拥有 0.2% 的份额。现在已经总结了旧版本的比例。与 1903 年和 1909 年一起是 11.5%。

Linux/Wine:windows 应用程序启动 windows 控制台命令并在 windows 上等待时在 linux 上不等待:如何修复?

Linux/Wine:windows 应用程序启动 windows 控制台命令并在 windows 上等待时在 linux 上不等待:如何修复?

如何解决Linux/Wine:windows 应用程序启动 windows 控制台命令并在 windows 上等待时在 linux 上不等待:如何修复??

除了一项功能外,我还使用 Wine 成功运行了 Windows 程序。该程序可以设置为在 texlive 发行版中启动 pdflatex,当它启动时,它等待查看结果是否成功,然后复制/移动文件。但是在 Linux 上,我无法安排它像在 Windows 上那样等待 pdflatex 完成,因此过早地复制/移动文件并且 pdflatex 无法找到它们。

有一个对话框可以用来保存任意命令,当我按下应用程序中的 pdflatex 按钮时,该命令将被执行。我将此对话框指向 Windows 上的 C:\texlive\2020\bin\win32\pdflatex.exe 并且它可以工作。除了不等待的问题外,我成功地放置了这个命令,以便在Linux上使用wine运行pdflatex。

Z:/usr/bin/gnome-terminal --wait -- /home/nonnull/bin/runlatex/runlatex.sh "%f"

通过将 runlatex.sh 中的最后一个命令设为 exec /bin/bash,终端保持打开状态,因此我可以看到 pdflatex 的所有输出,并知道它正在使用 runlatex.sh 必须找出的正确文件运行通过将传递给它的 Windows 路径转换为其实际路径。 pdflatex 以各种方式抱怨它在那里创建的文件,然后在运行期间不存在。即使终端是打开的,所以没有完成执行,应用程序抱怨 pdflatex 没有正确完成,甚至在 pdflatex 的输出文本完成向下滚动终端之前。当我省略 exec 时,应用程序的行为不会改变终端立即关闭时的命令 pdflatex 完成。

Wine 是怎么回事,命令在完成运行之前不会保持附加状态?我该怎么办?对可以绕过这个困难的命令或机制有什么建议吗?如果需要的话,我准备编写一个 win32 程序来进行调解。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计

Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计

WIN11地平线上出现,它的设置为开始滚动10月5日提前计划的推出,微软边缘93已经发布了两个实验功能的支持:菜单和一个全新设计的现代滚动条相匹配的良好作风的视窗 11。

Microsoft Edge 93 具有多项改进和一些新功能。例如,微软已经启用了对类似 Chrome 的标签组的支持,旨在帮助用户有效地查找标签,以便他们可以轻松切换和管理标签。

Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计改进

Edge 93 还支持 PDF 文档的“从上次中断的地方继续”。同样,您可以使用将鼠标悬停在支持的视频上时出现的新工具栏,轻松地以画中画模式观看视频。工具栏只是让您在画中画窗口中查看该视频。

垂直选项卡设计已更新为 edge://settings/appearance 中的一个新选项,以隐藏浏览器的标题栏。除了这些改进之外,微软还引入了对新实验性功能的支持:Windows 11 Visual Updates 和 Overlay 滚动条

第一个标志将打开云母效果,这是一种新的 Windows 11 独有的设计材料,可自动将桌面背景的颜色应用于活动窗口。云母效果仅适用于浏览器的标题栏,如下面的屏幕截图所示。

Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计改进

它还为 Edge 菜单和上下文菜单启用 Fluent Design 的亚克力效果(部分透明)。如果您在 Windows 11 上启用该标志,它将调整菜单字体的大小,使其看起来更大一些。除了字体变化,它还使一些按钮居中,包括最小化、最大化和关闭。

另一方面,Windows 11 和 Windows 10 都完全支持叠加滚动条。叠加滚动条标志为浏览器的默认滚动条提供了精简设计,并且还支持暗模式。

Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计改进

更重要的是,“覆盖滚动条”功能旨在与 Windows 11 应用程序(如设置和资源管理器)的外观和感觉相匹配。

为了尝试这些功能,您需要 Edge 93(稳定版)或更新版本。更新到最新版本后,打开 Edge 标志菜单并启用 Windows 11 视觉更新标志。

要尝试 Edge 93 中的新滚动条,请打开 Edge 的属性选项卡并将以下代码添加到目标字段:

--enable-features=OverlayScrollbar,OverlayScrollbarWinStyle,OverlayScrollbarWinStyleAnimation

微软可能会在未来几个月为 Windows 11 用户引入更多的 Edge 视觉更新。

MSMG ToolKit 11.7 支持 Windows 11 22000 和 Windows 10 21H2

MSMG ToolKit 11.7 支持 Windows 11 22000 和 Windows 10 21H2

我们已经多次报告了 MSMG ToolKit 。一个小工具,除其他外,用于删除 Windows 下的功能。集成更新或驱动程序等等。

使用 MSMG ToolKit 11.7,现在还支持 Windows 11(系统)和 Windows 10 21H2(系统和移除组件)。更改列表很长。这是一个概述:

MSMG ToolKit 11.7 支持 Windows 11 22000 和 Windows 10 21H2

• 使用 Tweak 更新了“Apply Tweaks”功能,以禁用Windows 11 源操作系统的 Windows 11 安装程序的硬件检查。

• bin 文件夹的更新:Windows 11 WADK (v10.0.22000.1)、7-zip v21.03 命令行二进制文件

• 适用于 Windows 11、Windows Server LTSC 2022 的“集成 Microsoft .NET Framework 3.5”功能

• Microsoft .NET Framework 3.5 Pack for MSMG Toolkit for Windows 11, Windows Server LTSC 2022

• Microsoft .NET Framework 4.8 Pack for Windows 7 / Server 2008 R2 和该包也已更新

• 更新了适用于 Windows 11 和 Windows Server LTSC 2022 的“Microsoft Windows Accessible Braille”功能

• 更新“集成多媒体受限编解码器”功能以集成适用于 Windows 10 LTSC 和服务器源操作系统的 Windows 10 杜比编解码器并更新编解码器包。

• 更新开放安全外壳 (SSH) 功能以支持 Windows 11

• 更新了“集成 Microsoft DaRT 工具”功能以支持 Windows 11、Windows Server LTSC 2022 + DebugTools

• 更新删除 Windows 组件功能以支持 Windows 10 1809、1903、1909、2004、20H1、20H2

• 由于错误而禁用 Windows 防火墙 Windows 组件的删除。

• 添加了适用于 Windows 10 的“包含 Windows 图标皮肤”功能。

• 更正了“WIM 管理器- 导出”功能中的错误,如果选择了所有 WIM 索引,则导出失败。

• 已修复函数“WIM Manger- Convert”中的错误,如果选择了所有 WIM 索引,则转换失败。

• 工具包代码优化

我们今天的关于windows 10上源码编译libjpeg-turbo和使用教程源码编译软件的分享就到这里,谢谢您的阅读,如果想了解更多关于AdDuplex:Windows 10 21H1 和 Windows 11 首次进入快速增、Linux/Wine:windows 应用程序启动 windows 控制台命令并在 windows 上等待时在 linux 上不等待:如何修复?、Microsoft Edge 93 在 Windows 11 和 Windows 10 上获得设计、MSMG ToolKit 11.7 支持 Windows 11 22000 和 Windows 10 21H2的相关信息,可以在本站进行搜索。

本文标签: